@Nonnull
	public static Map<String, byte[]> generate(@Nonnull Workspace workspace,
	                                           @Nonnull Map<String, JvmClassInfo> inputMap) throws IOException {
		Map<String, byte[]> out = new HashMap<>();

		// Write the parameter passed classes to a temp jar
		Map<String, byte[]> classMap = new HashMap<>();
		Map<Type, ClassNode> nodes = new HashMap<>();
		inputMap.forEach((name, info) -> {
			ClassReader cr = info.getClassReader();
			ClassNode node = new ClassNode();
			cr.accept(node, ClassReader.SKIP_FRAMES);
			classMap.put(name + ".class", info.getBytecode());
			nodes.put(Type.getObjectType(node.name), node);
		});

		// Read into JPhantom
		Options.V().setSoftFail(true);
		Options.V().setJavaVersion(8);
		ClassHierarchy hierarchy = createHierarchy(classMap);
		ClassMembers members = createMembers(classMap, hierarchy);
		classMap.forEach((name, raw) -> {
			if (name.contains("$"))
				return;
			try {
				ClassReader cr = new ClassReader(raw);
				cr.accept(new ClassPhantomExtractor(hierarchy, members), 0);
			} catch (Throwable t) {
				logger.debug("Phantom extraction failed: {}", name, t);
			}
		});

		// Remove duplicate constraints for faster analysis
		Set<String> existingConstraints = new HashSet<>();
		ClassAccessStateMachine.v().getConstraints().removeIf(c -> !existingConstraints.add(c.toString()));

		// Execute and populate the current resource with generated classes
		try {
			JPhantom phantom = new JPhantom(nodes, hierarchy, members);
			phantom.run();
			phantom.getGenerated().forEach((k, v) -> {
				// Only put items not found in the workspace.
				// We may call the generator on a small scope, and thus create phantoms of classes that
				// exist in the workspace, but were not in the provided scope.
				String name = k.getInternalName();
				if (workspace.findJvmClass(name) == null)
					out.put(name, decorate(v));
			});
			logger.debug("Phantom analysis complete, generated {} classes", out.size());
		} catch (Throwable t) {
			logger.error("Phantom analysis encountered an exception.", t);
		} finally {
			// Cleanup
			Phantoms.refresh();
			Phantoms.V().getLookupTable().clear();
			ClassAccessStateMachine.refresh();
			FieldAccessStateMachine.refresh();
			MethodAccessStateMachine.refresh();
		}
		return out;
	}
@param workspace
		Workspace to check for class existence within.
@param inputMap
		Input map of classes to create phantoms for.

@return Map of phantom classes.

@throws IOException
		When {@link JPhantom#run()} fails.
recaf-core/src/main/java/software/coley/recaf/services/phantom/JPhantomGenerator.java