How I Resolved Java Dependency : A Developer's Journey

Background
While working on a legacy integration component, I faced an odd situation. I had a simple .java
file to test locally — nothing complex — but it refused to compile without dozens of dependencies. Normally, I would let Maven or Gradle handle it. But this time, there was a constraint: no internet access and all jars were already available in a different environment called primary runtime.
I was working in sandbox, a restricted shell, and needed to compile and run the Java file using the jars from primary runtime. The immediate thought was — "Let’s just reuse primary runtime's classpath." But something told me not to rush. So I paused and started questioning:
Why not just point restricted shell’s classpath to primary runtime’s?
That would’ve been the easiest route — but not the safest one. primary runtime is a running, production-aligned environment, and reusing its paths might lead to side effects or hidden coupling. Moreover, restricted shell needed to be independently operable. So I took the long route — figuring out the exact jars needed from that classpath dump.
Challenges
No Internet: I couldn't use
mvn dependency:resolve
, or any remote repo to download missing jars.Classpath Hell: There were 1000+ jars in primary runtime’s classpath — copying everything wasn’t ideal.
No Maven Setup: I wasn’t allowed to modify existing pom.xml files or setup a new Maven project with remote dependencies.
Unclear Dependencies: I had no clear view of which jars the simple
.java
file really needed.
My Attempted Fixes
I explored a few dead ends initially:
Tried running
mvn archetype:generate
but it failed due to no internet.Thought of copying all jars blindly to restricted shell — but it was clunky, slow, and unnecessary.
Tried pointing classpath to primary runtime, but dropped it for reasons stated earlier.
Spent hours fiddling with Maven local repo population using
install:install-file
— but registering 1000 jars manually? Not scalable.
Eureka Moment: Using java -verbose:class
I remembered a classic trick:
Use
java -verbose:class
to see which classes (and from which jars) are actually being loaded at runtime.
This was the game-changer. Here's what I did:
I compiled and ran the
.java
file in a working setup (outside mql).Used this command:
java -verbose:class MyTest > loaded_classes.log
Parsed the log file using:
grep '\[Opened' loaded_classes.log | awk -F'Opened ' '{print $2}' | sort | uniq
This gave me a clean list of jar files that were actually used.
From there, I copied only the required jars to restricted shell.
Appended them to classpath:
export CLASSPATH=/path/to/needed1.jar:/path/to/needed2.jar:. javac MyTest.java java MyTest
And guess what? It worked.
Bonus Tip
Once you have the filtered list of required jars, you can even archive them for future isolated runs:
mkdir essential_jars
cp $(cat required_jars.txt) essential_jars/
Why This Was Worth It
I avoided coupling restricted shell to primary runtime.
Isolated environment ensured future scalability.
Built a repeatable method for similar future setups.
Learned how to smartly reduce dependency trees without a build tool.
Final Thoughts
This whole exercise reminded me why developer productivity isn’t always about using fancier tools — sometimes, a bit of old-school debugging and shell scripting goes a long way.
It took a full day, but I’ve now captured this experience, learned how to document it, and even published internally and externally — something I never used to do.
If you're stuck with dependency resolution in an isolated Java environment, don’t panic. Just trace the classes and filter the jars.
This blog may help you save hours next time you're dealing with dependency hell.
Subscribe to my newsletter
Read articles from Fayaz Khan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Fayaz Khan
Fayaz Khan
Hi, I’m Fayaz Khan — a PLM Solution Architect with deep hands-on experience in 3DEXPERIENCE, real-world integrations, and enterprise system behavior. I work at the intersection of engineering, security, and systems thinking, navigating between PLM platforms, cloud infrastructure, APIs, and practical business needs. I prefer digging into why something works (or breaks), rather than just how to configure it. My writing is an attempt to document the often-overlooked details — the silent bugs, the edge cases, the security gaps — and sometimes, the mental models that help me make sense of it all.