Code Monkey home page Code Monkey logo

Comments (22)

JiaRG avatar JiaRG commented on May 26, 2024

cn.myperf4j.asm.aop.ProfilingTransformer#getBytes

  private byte[] getBytes(ClassLoader loader,
                          String className,
                          byte[] classFileBuffer) {
      ClassReader cr = new ClassReader(classFileBuffer);
      ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS) {
          @Override
          protected ClassLoader getClassLoader() {
              return Thread.currentThread().getContextClassLoader();
          }
      };
      ClassVisitor cv = new ProfilingClassAdapter(cw, className);
      cr.accept(cv, ClassReader.EXPAND_FRAMES);
      return cw.toByteArray();
  }

采用线程本地类加载器后,自测在 tomcat 8.5 上可以监控 tomcat 本身和内部类

此处的改动就限制死了加载的class文件必须是使用 jdk 1.7 以上版本编译过的

see: https://www.java67.com/2020/04/javalangverifyerror-expecting-stack-map.html

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

现在 MyPerf4J 只支持 1.7 及其之上的版本,这个改动的影响面比较大,你测试了哪些场景?

这块代码逻辑兼容了 PlainJava、Tomcat、SpringBoot、Flink 等场景,如果你的解决方案同样适用这些场景的话,欢迎提交 PR

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

前三者没问题,Flink 没环境测。。。

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

这种写法你是在哪儿看到的?当年我写这段代码的时候对于使用 COMPUTE_MAXS 还是 COMPUTE_FRAMES 还是比较困惑的

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

image

堆栈显示这报的错,看了下里面有获取 ClassLoader 的方法,就试了下

那俩变量就 google 下,看到了那篇文章的内容😁

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

有想法、运气不错;不过,你这个改动得进行全面的测试才行

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

image

翻了下文档,读的时候不需要计算,要不会有性能损耗,写的时候才重新计算

    private byte[] getBytes(ClassLoader loader,
                            String className,
                            byte[] classFileBuffer) {
        ClassReader cr = new ClassReader(classFileBuffer);
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES) {
            @Override
            protected ClassLoader getClassLoader() {
                return Thread.currentThread().getContextClassLoader();
            }
        };
        ClassVisitor cv = new ProfilingClassAdapter(cw, className);
        cr.accept(cv, ClassReader.SKIP_FRAMES);
        return cw.toByteArray();
    }

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

翻了下文档,读的时候不需要计算,要不会有性能损耗,写的时候才重新计算

这个方案有问题:
image

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

这是跟其它的 agent 冲突了吧,我本地用 jdk20 起了一个 springboot2.7.8 的 demo 没问题

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

image

出现了个这问题😓

2023-04-10 22:38:00.014 [MyPerf4J] ERROR [MyPerf4J-LightWeightScheduler-0] JvmMetricsScheduler.processThreadMetrics(1681137420014, 1681137420014, 1681137480014) Could not initialize class cn.myperf4j.base.metric.collector.JvmThreadCollector
java.lang.NoClassDefFoundError: Could not initialize class cn.myperf4j.base.metric.collector.JvmThreadCollector
        at cn.myperf4j.core.scheduler.JvmMetricsScheduler.processThreadMetrics(JvmMetricsScheduler.java:139)
        at cn.myperf4j.core.scheduler.JvmMetricsScheduler.run(JvmMetricsScheduler.java:72)
        at cn.myperf4j.core.LightWeightScheduler.runTask(LightWeightScheduler.java:100)
        at cn.myperf4j.core.LightWeightScheduler.runAllTasks(LightWeightScheduler.java:93)
        at cn.myperf4j.core.LightWeightScheduler.access$200(LightWeightScheduler.java:18)
        at cn.myperf4j.core.LightWeightScheduler$1.run(LightWeightScheduler.java:85)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:358)
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.reflect.InaccessibleObjectException: Unable to make private static native java.lang.Thread[] java.lang.Thread.getThreads() accessible: module java.base does not "opens java.lang" to unnamed module @6a41eaa2 [in thread "MyPerf4J-LightWeightScheduler-1"]
        at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:387)
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:363)
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:311)
        at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:201)
        at java.base/java.lang.reflect.Method.setAccessible(Method.java:195)
        at cn.myperf4j.base.metric.collector.JvmThreadCollector.reflectGetThreadsMethod(JvmThreadCollector.java:34)
        at cn.myperf4j.base.metric.collector.JvmThreadCollector.<clinit>(JvmThreadCollector.java:27)
        ... 12 more

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

ThreadMXBean 里面不是有现成的方法可以获取到数据么,为啥要反射呢?

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

这是跟其它的 agent 冲突了吧,我本地用 jdk20 起了一个 springboot2.7.8 的 demo 没问题

不是

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

image

出现了个这问题😓

2023-04-10 22:38:00.014 [MyPerf4J] ERROR [MyPerf4J-LightWeightScheduler-0] JvmMetricsScheduler.processThreadMetrics(1681137420014, 1681137420014, 1681137480014) Could not initialize class cn.myperf4j.base.metric.collector.JvmThreadCollector
java.lang.NoClassDefFoundError: Could not initialize class cn.myperf4j.base.metric.collector.JvmThreadCollector
        at cn.myperf4j.core.scheduler.JvmMetricsScheduler.processThreadMetrics(JvmMetricsScheduler.java:139)
        at cn.myperf4j.core.scheduler.JvmMetricsScheduler.run(JvmMetricsScheduler.java:72)
        at cn.myperf4j.core.LightWeightScheduler.runTask(LightWeightScheduler.java:100)
        at cn.myperf4j.core.LightWeightScheduler.runAllTasks(LightWeightScheduler.java:93)
        at cn.myperf4j.core.LightWeightScheduler.access$200(LightWeightScheduler.java:18)
        at cn.myperf4j.core.LightWeightScheduler$1.run(LightWeightScheduler.java:85)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:358)
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.reflect.InaccessibleObjectException: Unable to make private static native java.lang.Thread[] java.lang.Thread.getThreads() accessible: module java.base does not "opens java.lang" to unnamed module @6a41eaa2 [in thread "MyPerf4J-LightWeightScheduler-1"]
        at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:387)
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:363)
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:311)
        at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:201)
        at java.base/java.lang.reflect.Method.setAccessible(Method.java:195)
        at cn.myperf4j.base.metric.collector.JvmThreadCollector.reflectGetThreadsMethod(JvmThreadCollector.java:34)
        at cn.myperf4j.base.metric.collector.JvmThreadCollector.<clinit>(JvmThreadCollector.java:27)
        ... 12 more

注意看:module java.base does not "opens java.lang" to unnamed module

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

ThreadMXBean 里面不是有现成的方法可以获取到数据么,为啥要反射呢?

性能差,线程数很多时会影响应用

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

这是跟其它的 agent 冲突了吧,我本地用 jdk20 起了一个 springboot2.7.8 的 demo 没问题

不是

有复现的 demo 么,图里也看不出啥来,或者加载的那个类有啥特别的

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

这是跟其它的 agent 冲突了吧,我本地用 jdk20 起了一个 springboot2.7.8 的 demo 没问题

不是

有复现的 demo 么,图里也看不出啥来,或者加载的那个类有啥特别的

从代码上看没什么特别的:

  • class A extends B
  • 在加载 B 时抛出 java.lang.ClassCircularityError: A

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

你试试这个方案:

    private byte[] getBytes(final ClassLoader loader,
                            String className,
                            byte[] classFileBuffer) {
        final ClassReader cr = new ClassReader(classFileBuffer);
        final ClassWriter cw = new ClassWriter(cr, needComputeMaxs(loader) ? COMPUTE_MAXS : COMPUTE_FRAMES) {
            @Override
            protected ClassLoader getClassLoader() {
                return loader != null ? loader : super.getClassLoader();
            }
        };
        final ClassVisitor cv = new ProfilingClassAdapter(cw, className);
        cr.accept(cv, EXPAND_FRAMES);
        return cw.toByteArray();
    }

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

这是跟其它的 agent 冲突了吧,我本地用 jdk20 起了一个 springboot2.7.8 的 demo 没问题

不是

有复现的 demo 么,图里也看不出啥来,或者加载的那个类有啥特别的

从代码上看没什么特别的:

  • class A extends B
  • 在加载 B 时抛出 java.lang.ClassCircularityError: A

那说明 B extends A ? 要么类库出现了多个版本了

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

这是跟其它的 agent 冲突了吧,我本地用 jdk20 起了一个 springboot2.7.8 的 demo 没问题

不是

有复现的 demo 么,图里也看不出啥来,或者加载的那个类有啥特别的

从代码上看没什么特别的:

  • class A extends B
  • 在加载 B 时抛出 java.lang.ClassCircularityError: A

那说明 B extends A ? 要么类库出现了多个版本了

B 不会继承 A 否则编译都通不过;还是类加载的问题

from myperf4j.

JiaRG avatar JiaRG commented on May 26, 2024

-XX:+TraceClassLoading 看下没 agent 的时候和有 agent 的时候那个类是从哪加载的。。。剩下我能想到的就只有那个类所在的类库出现了多个版本了,最好提供个 demo 吧😢

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

@JiaRG
如果以这个为 v0.1:

    private byte[] getBytes(final ClassLoader loader,
                            String className,
                            byte[] classFileBuffer) {
        final ClassReader cr = new ClassReader(classFileBuffer);
        final ClassWriter cw = new ClassWriter(cr, needComputeMaxs(loader) ? COMPUTE_MAXS : COMPUTE_FRAMES) {
            @Override
            protected ClassLoader getClassLoader() {
                return loader != null ? loader : super.getClassLoader();
            }
        };
        final ClassVisitor cv = new ProfilingClassAdapter(cw, className);
        cr.accept(cv, EXPAND_FRAMES);
        return cw.toByteArray();
    }

以这个为 v1:

    private byte[] getBytes(ClassLoader loader,
                            String className,
                            byte[] classFileBuffer) {
        ClassReader cr = new ClassReader(classFileBuffer);
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES) {
            @Override
            protected ClassLoader getClassLoader() {
                return Thread.currentThread().getContextClassLoader();
            }
        };
        ClassVisitor cv = new ProfilingClassAdapter(cw, className);
        cr.accept(cv, ClassReader.SKIP_FRAMES);
        return cw.toByteArray();
    }

那么,在没有 MyPerf4J 和 有 MyPerf4J v0.1 与 v1 的版本在添加了 -XX:+TraceClassLoading 参数后的日志(做了脱敏与过滤)为:
image

你可以看到有问题的 v1 版本的类加载与另外两个明显不同,v1 版本里 MqttWireMessage 加载了 2 次

from myperf4j.

LinShunKang avatar LinShunKang commented on May 26, 2024

你试试这个方案:

    private byte[] getBytes(final ClassLoader loader,
                            String className,
                            byte[] classFileBuffer) {
        final ClassReader cr = new ClassReader(classFileBuffer);
        final ClassWriter cw = new ClassWriter(cr, needComputeMaxs(loader) ? COMPUTE_MAXS : COMPUTE_FRAMES) {
            @Override
            protected ClassLoader getClassLoader() {
                return loader != null ? loader : super.getClassLoader();
            }
        };
        final ClassVisitor cv = new ProfilingClassAdapter(cw, className);
        cr.accept(cv, EXPAND_FRAMES);
        return cw.toByteArray();
    }

@JiaRG 这个 v0.1 的版本,你试了么?

from myperf4j.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.