Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassNotFoundException is thrown in a non-Spring Boot application when excluding LatencyUtils #3287

Closed
izeye opened this issue Jul 13, 2022 · 8 comments
Labels
bug A general bug module: micrometer-core An issue that is related to our core module
Milestone

Comments

@izeye
Copy link
Contributor

izeye commented Jul 13, 2022

Describe the bug

Since #1599, a Spring Boot application seems to work, but a non-Spring Boot application doesn't seem to work with the following exception:

Exception in thread "main" java.lang.NoClassDefFoundError: org/LatencyUtils/IntervalEstimator
	at io.micrometer.core.instrument.simple.SimpleMeterRegistry.newTimer(SimpleMeterRegistry.java:95)
	at io.micrometer.core.instrument.MeterRegistry.lambda$timer$2(MeterRegistry.java:318)
	at io.micrometer.core.instrument.MeterRegistry.getOrCreateMeter(MeterRegistry.java:618)
	at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:570)
	at io.micrometer.core.instrument.MeterRegistry.timer(MeterRegistry.java:316)
	at io.micrometer.core.instrument.Timer$Builder.register(Timer.java:399)
	at com.izeye.sample.LatencyUtilsExcludeApplication.main(LatencyUtilsExcludeApplication.java:17)
Caused by: java.lang.ClassNotFoundException: org.LatencyUtils.IntervalEstimator
	at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	... 7 more
Caused by: java.lang.ClassNotFoundException: org.LatencyUtils.IntervalEstimator

Environment

  • Micrometer version: 1.8.8
  • Micrometer registry: SimpleMeterRegistry
  • OS: macOS
  • Java version:
openjdk version "1.8.0_333"
OpenJDK Runtime Environment (build 1.8.0_333-b02)
OpenJDK 64-Bit Server VM (build 25.333-b02, mixed mode)

To Reproduce

Run LatencyUtilsExcludeApplication.main() from https://github.com/izeye/micrometer-latencyutils-exclude

Expected behavior

The exception is not thrown.

Additional context

./gradlew bootRun from https://github.com/izeye/micrometer-spring-boot-latencyutils-exclude works.

@shakuzen shakuzen added bug A general bug module: micrometer-core An issue that is related to our core module labels Jul 13, 2022
@shakuzen shakuzen added this to the 1.8.x milestone Jul 13, 2022
@shakuzen
Copy link
Member

That's an interesting difference I guess caused by different class loaders. Thank you for catching it, and for adding the test for it. We'll have to make more changes to make things really work without LatencyUtils on the classpath. At least now we'll be able to unit test it.

@cvgaviao
Copy link

I was bitten by this issue today.

The workaround would be to add the LatencyUtils dependency with compile scope into my project's pom.xml ?

@jonatan-ivanov
Copy link
Member

@cvgaviao Since the error is coming from the ClassLoader, it seems the JVM wants to load that class which is a runtime process, so adding it as a compile-time dependency should not help, it need to be a runtime dependency, being on your classpath.

@shakuzen shakuzen modified the milestones: 1.8.x, 1.8.9 Jul 28, 2022
@shakuzen
Copy link
Member

I was bitten by this issue today.

The workaround would be to add the LatencyUtils dependency with compile scope into my project's pom.xml ?

@cvgaviao You shouldn't need to add the LatencyUtils dependency since Micrometer already declares it as a (runtime) dependency. This should only be an issue if you are explicitly excluding the LatencyUtils dependency. Are you?

I've pushed a fix for this issue. Our test is passing now. It would be appreciated if anyone excluding the LatencyUtils dependency and was having this issue can check if it is fixed for you in the latest 1.8.9-SNAPSHOT versions before we cut a release.

@cvgaviao
Copy link

cvgaviao commented Jul 28, 2022

@cvgaviao Since the error is coming from the ClassLoader, it seems the JVM wants to load that class which is a runtime process, so adding it as a compile-time dependency should not help, it need to be a runtime dependency, being on your classpath.

@shakuzen, as I was in a urgency matter to show something to my boss, so I declared it in my pom as a compile dependency and it have worked. It seems that the fact that micrometer have it as a runtime dependency don't ensure that some maven plugins, as the assembly-plugin or dependency-plugin should consider it to be copied.

Perhaps micrometer could use the maven-shade-plugin and generate a uber jar containing the LatencyUtils classes?

@shakuzen
Copy link
Member

Perhaps micrometer could use the maven-shade-plugin and generate a uber jar containing the LatencyUtils classes?

We have previously considered this in #614 and decided to not go that direction. I am still inclined to agree with the decision made then.

It seems that the fact that micrometer have it as a runtime dependency don't ensure that some maven plugins, as the assembly-plugin or dependency-plugin should consider it to be copied.

For us to investigate such an issue further, it would be very helpful to have a minimal sample project that reproduces the issue. If you would like to provide one, please open a new issue that describes the problem and gives us a way to reproduce it.

@cvgaviao
Copy link

@shakuzen, me and my team have decided not to wait for you guys to investigate this.
It is not difficult to understand that a "runtime" or "provided" scoped jars must be available in the classpath as well as any "compile" ones.

I presume that Spring has it on its dependency tree, but as we don't use spring we created a project and wrapped the micrometer and LatencyUtils on it. moved on.

I just recommend you add this information in your docs, because certainly others will have the same issue.

thanks anyway.

@shakuzen
Copy link
Member

shakuzen commented Aug 4, 2022

It is not difficult to understand that a "runtime" or "provided" scoped jars must be available in the classpath as well as any "compile" ones.

That's not exactly the case. I've added documentation explaining the dependency situation and requirements with micrometer-metrics/micrometer-docs#241 which is now published at https://micrometer.io/docs/concepts#_dependencies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A general bug module: micrometer-core An issue that is related to our core module
Projects
None yet
Development

No branches or pull requests

4 participants