I am the author of the moderately popular (⭐ 2k) Dependency Analysis Gradle Plugin, a static analysis tool that helps Gradle build authors maintain...
For further actions, you may consider blocking this person and/or reporting abuse
Oh yes :) aws is "awesome", I needed one aws library, I ended up with over 60 dependencies for that ...
Cursed is a good way to describe most software ecosystems
If it has dependencies, it has an attack surface. Java’s issue isn’t “too many packages” — it’s the transitive trust model combined with almost no runtime verification. When you’re pulling 200+ libraries just to print “Hello World,” you’re not just cursed… you’re handing adversaries 200 potential injection points before your code even runs.
This resonates so hard! The constant pool issue with non-javac compilers is something I've struggled with too. It's frustrating when static analysis breaks because different compilers handle constants differently. Your plugin sounds absolutely essential for navigating these dependency nightmares. Great write-up
The fact that most of the other popular ecosystems are worse doesn't change the fact that yes, Java package management is cursed.
The big benefits that Java has are the large standard library, and the large well-supported extension libraries (apache commons, jetty, etc) which help avoid the left-pad insanity of some other platforms.
The big disadvantage is Maven. Entangling build automation with dependency resolution is as big a crime as bundling third-party dependencies invisibly into a library package.
Gradle seems to resolve the superficial problems of Maven while slavishly reproducing the fundamental problems. Doing anything slightly beyond the basic requires understanding multiple independent undocumented plugins.
While the Java ecosystem certainly has its share of historical baggage and uneven tooling, calling it “cursed” ignores the fact that these pain points stem from a huge, diverse, and long-lived platform that still enables massive-scale engineering. Most of the issues you describe are solvable—not signs of a curse—just the natural friction of an ecosystem powerful enough to outlive every design trend thrown at it.
A very insightful article. When libraries use shadowing / shading that's always an issue. It's often an excuse / escape hatch for the library authors to avoid having to update the dependency, and then the shaded version is left to rot. Good luck explaining this to cyber security and their container scanners. There are valid use cases for shadowing, but hiding or pinning your dependency isn't one.
Updating isn't always straight forward either. We had at least two major issues this year arising from spring patch level updates. People either don't understand or outright ignore semantic versioning is another major pain.
Gradle also partly bears the blame. We had the issue that a transitive dependency had a CVE we needed to fix ASAP (the container scanners were at it again!) and we wanted to do that in gradle. Tried 6 different ways to do so (two outdated and two experimental) but nothing worked. Turned out that a BOM was to blame and resolution works differently there. The only workaround to "fix" this was to introduce a direct dependency from our project to the transitive dependency (which is semantically not needed) just to be able to upgrade the transitive dependency.
Fun! -_-
I solved the log4shell issue in my team by using a reject rule. It might make the build fail if it prevented resolving a version but it did prevent bad versions entering the build!
yes it is