skylot/jadx · error · JadxRuntimeException

Classpath already loaded

Error message

Classpath already loaded

What it means

Thrown by ClspGraph.addClasspath() when nameMap is already non-null, meaning a classpath ClsSet has already been registered on this ClspGraph instance. The classpath can only be loaded once; subsequent calls are rejected to prevent duplicate or conflicting class data.

Source

Thrown at jadx-core/src/main/java/jadx/core/clsp/ClspGraph.java:53

	private final Set<String> missingClasses = new HashSet<>();

	public ClspGraph(RootNode rootNode) {
		this.root = rootNode;
	}

	public void loadClsSetFile() throws IOException, DecodeException {
		ClsSet set = new ClsSet(root);
		set.loadFromClstFile();
		addClasspath(set);
	}

	public void addClasspath(ClsSet set) {
		if (nameMap == null) {
			nameMap = new HashMap<>(set.getClassesCount());
			set.addToMap(nameMap);
		} else {
			throw new JadxRuntimeException("Classpath already loaded");
		}
	}

	public void addApp(List<ClassNode> classes) {
		if (nameMap == null) {
			nameMap = new HashMap<>(classes.size());
		}
		for (ClassNode cls : classes) {
			addClass(cls);
		}
	}

	public void initCache() {
		fillSuperTypesCache();
		fillImplementsCache();
	}

	public boolean isClsKnown(String fullName) {

View on GitHub (pinned to e738a26571)

Solutions

  1. Create a new ClspGraph/RootNode instance for each independent classpath load.
  2. Check whether nameMap is already populated before calling addClasspath() — guard the call with a null check.
  3. Refactor the initialization flow to ensure loadClsSetFile() or addClasspath() is called exactly once per graph lifetime.

Example fix

// before
//   graph.addClasspath(set1);
//   graph.addClasspath(set2); // throws
// after
//   if (graph.getNameMap() == null) {
//       graph.addClasspath(set);
//   }
Defensive patterns

Strategy: validation

Validate before calling

// Check before adding classpath
ClspGraph graph = root.getClspGraph();
// nameMap is private; use a guard method or ensure single initialization
// Safest: create a fresh RootNode for each independent classpath load
RootNode root = new RootNode(args);
root.getClspGraph().loadClsSetFile(); // call exactly once
// Do NOT call loadClsSetFile() or addClasspath() again on this root

Try / catch

try {
    graph.addClasspath(set);
} catch (JadxRuntimeException e) {
    if (e.getMessage().equals("Classpath already loaded")) {
        logger.warn("Classpath already loaded on this graph, skipping.");
        // Safe to ignore if the existing classpath is sufficient
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling addClasspath() or loadClsSetFile() twice on the same ClspGraph instance. This commonly happens in code that re-initializes a RootNode or attempts to merge multiple classpath sets into one graph.

Common situations: Reusing a JadxDecompiler or RootNode instance across multiple decompilation runs without resetting the ClspGraph. Plugin or integration code that loads the classpath eagerly and then the core also loads it.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/c2703dedc596ba3c. Report an issue: GitHub.