From 6df8ead7c2fdfe12e2b71d25edcab0abf4b93c89 Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Fri, 11 Feb 2022 11:28:06 +0200 Subject: [PATCH] Possibility to provide classpath dir. Updated help and documentation. --- doc/example-thumbnail.png | Bin 0 -> 22858 bytes doc/index.html | 931 ++++++++++-------- doc/index.org | 111 ++- .../commandline/CommandlineConfiguration.java | 17 +- .../inspector/java/commandline/Main.java | 25 +- 5 files changed, 615 insertions(+), 469 deletions(-) create mode 100644 doc/example-thumbnail.png diff --git a/doc/example-thumbnail.png b/doc/example-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..04f4195a0ed4c83317eb2959bd738c57c9def15a GIT binary patch literal 22858 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 - + + + + + + JavaInspect - Utility to visualize java software - - - - - + + + @@ -14,247 +200,116 @@ footer {background-color: #111 !important;} pre {background-color: #111; color: #ccc;} - + -
-

JavaInspect - Utility to visualize java software

+
+

JavaInspect - Utility to visualize java software

+ -
-

1 General

+
+

1 General

- +https://github.com/abargnesi/javainspect + +
-
-

1.1 Source code

+
+

1.1 Source code

-
-

2 Goal and operating principle

+
+

2 Goal and operating principle

Goal: simplify/speed up understanding the computer program code by @@ -266,15 +321,15 @@ automatically visualizing its structure.

-JavaInspect can be used as a standalone commandline utility as well as -java library. JavaInspect uses primarily Java built-in reflection to +JavaInspect can be used as a standalone commandline utility as well as +java library. JavaInspect uses primarily Java built-in reflection to discover and visualize any part of Java program.

-JavaInspect currently has no GUI, configuration files, embedded -scripting support, direct Maven or Ant integration. See usage to learn -how to instuct Javainspect what to do. +JavaInspect currently has no graphical user interface, configuration +files, embedded scripting support, direct Maven, Gradle or Ant +integration. See usage to learn how to instuct Javainspect what to do.

@@ -288,111 +343,207 @@ bitmap graph in PNG or SVG format. Notes:

-
-

3 Example graphs

+
+

3 Example graphs

    -
  • A very simple example: +
  • +A very simple example: +

    -
    -

    example.png +

    +

    example-thumbnail.png

    -
    +

Graph legend:

-
-

legend.png +

+

legend.png

-
- +
-
-

4 Usage

+
+

4 Installation

-JavaInspect can be controlled in 2 different ways: +GraphViz - shall be installed on the computer.

- + +

+On Ubuntu/Debian GraphViz can be installed using: +

+
+
sudo apt-get install graphviz
+
-
-

4.1 usage as commandline utility

-

-To enable commandline support, (study and) execute script: +To use JavaInspect via Java API, no further installation is +needed. JavaInspect will be embedded into your project as dependency. +This is described in usage via Java API. It will expect GraphViz to be +available in the system. +

+ +

+To use JavaInspect as a commandline tool, JavaInspect source +repository has to be cloned locally: See Source code. +

+ +

+Then study and execute installation script:

 commandline launcher/install
+
+ +

+After installation, new commandline tool should be available +

+
+javainspect
 
+

-Warning: It was tested only on Debian Stretch linux. +Quick commandline usage help can be viewed by issuing

+
+javainspect --help
+
+
+
+
+

5 Usage

+

-Available commandline arguments: +JavaInspect can be controlled in 2 different ways:

+ +
+ +
+

5.1 Usage as commandline utility

+
+
+
+

5.1.1 Available commandline arguments

+

--j (existing files)…
-    JAR file(s) to render.
-
--n (mandatory, string)
-    Graph name.
-
-–debug
-    Show debug info.
-
--k
-    Keep dot file.
-
--h
-    Hide orphaned classes.
-
--w (one to many strings)…
-    Whitelist glob(s).
-
--b (one to many strings)…
-    Blacklist glob(s).
-
--d (existingdirectory)
-    Target directory. Default is current directory.
-
--t (options: png, svg)
-    Target image type. Default is: svg.
-

-
-
-
-

4.2 usage via Java API

-
+-j (existing files)…
+    JAR file(s) to render.
+
+-c (existing directories)…
+    Classpath directories
+
+-n (string)
+    Graph name. (default: "graph")
+
+–debug
+    Show debug info.
+
+-h, –help
+    Show commandline usage help.
+
+-k
+    Keep dot file.
+
+-ho
+    Hide orphaned classes.
+
+-w (one to many strings)…
+    Whitelist glob(s).
+
+-b (one to many strings)…
+    Blacklist glob(s).
+
+-r (one to many strings)…
+    root class(es).
+
+-d (existing directory)
+    Target directory. Default is current directory.
+
+-t (options: png, svg)
+    Target image type. Default is: svg.
+

+
+
+
+

5.1.2 Specifying classes to render

+
+

+Normal Java application has immense complexity. In addition to code +that was directly written by particular project developers, lots of +functionality is typically added as frameworks or libraries to the +project. In addition there is significant Java standard library. +

+ +

+Because JavaInspect uses reflection, it does not easily distinguish +between those. In normal situation you would rather want to visualize +only code that was developed specifically for your project and leave +frameworks like Spring etc. out. If you visualize all classes that are +possibly reachable from you project, you will easily get huge and +incomprehensible graph. +

+ +

+JavaInspect can digest compiled Java classes in 2 modes: +

+
    +
  1. Provide list of Jar files. Use -j option.
  2. +
  3. Provide list of filesystem directories that can be used as +classpath root. Use -c option.
  4. +
+ +

+Currently JavaInspect uses following algorithm to add classes to +rendered graph: +

+ +
    +
  • All classes that were found in Jar files are added to graph by default.
  • +
  • None of the classes that were found in filesystem directories are +added to the graph by default (unless explicitly referenced). (TODO: +for consistency it would be better to add them too by default)
  • +
  • If whitelist is specified (-w option) everything that is not +matched by whitelist pattern(s) will be removed from the graph.
  • +
  • If blacklist is specified (-b option) everything that is matched +by blacklist pattern(s) will be removed from the graph.
  • +
  • Root classes can be specified using -r option. Root classes will +be added to the graph. JavaInspect will then try to recursively +discover all classes that were referenced by root class and add +those also to the graph.
  • +
+
+
+
+ +
+

5.2 Usage via Java API

+

Requires that classes to be visualised are available in the classpath.

@@ -403,15 +554,13 @@ up with 2 solutions:

    -
  1. Add JavaInspect library in your project as a dependency. -
  2. +
  3. Add JavaInspect library in your project as a dependency.
  4. Create new Java project for the purpose visualizing your other projects and include JavaInspect and your projecs binary artifacts (Jar's) into new project classpath. Built binary Jar's (with no source code) are sufficient because JavaInspect operates via -reflection. -
  5. +reflection.

@@ -425,48 +574,40 @@ product or project artifact I'm just willing to visualize. Control code in general does the following:

    -
  1. Create graph object. -
  2. +
  3. Create graph object.
  4. Java reflection/classloaders does not provide mechanism for discovering all classes under given package. Therefore you need to declare at least some classes to be added to the graph by manually adding individual classes to the graph. For every class added to the graph, GraphViz will recursively inspect it and add all -referecned classes to the graph as well. -
  5. +referecned classes to the graph as well.
  6. Graphs easilly get very big and complex so optionally we filter important code using classname glob patterns based blacklist and/or -whitelist. -
  7. +whitelist.
  8. Optionally we can tune some rendering parameters like:
    • Possibility to remove orphaned classes (classes with no -references) from the graph. -
    • +references) from the graph.
    • Specify target directory for generated visualization -files. (Default is current directory) -
    • -
    • Keep intermediate GraphViz dot file for later inspection. -
    • -
    -
  9. -
  10. Render graph. -
  11. +files. (Default is current directory) +
  12. Keep intermediate GraphViz dot file for later inspection.
  13. + +
  14. Render graph.
-
-

4.2.1 example 1: individually picked objects

-
+
+

5.2.1 Example 1: individually picked objects

+

This example demonstrates generating of class graph from hand picked classes and visualizing GraphViz itself.

- -
// Create graph
+
+// Create graph
 final ClassGraph graph = new ClassGraph();
 
 // Add some random object to the graph. GraphViz will detect Class from
@@ -490,7 +631,6 @@ graph.generateGraph("JavaInspect");
 Note: if desired, more compact version of the above:
 

-
new ClassGraph().add(randomObject, RandomClass.class)
                 .setKeepDotFile(true).generateGraph("JavaInspect");
 
@@ -501,34 +641,29 @@ Note: if desired, more compact version of the above: Result:

-
-

4.2.2 example 2: GraphViz embedded in another project

-
+
+

5.2.2 Example 2: GraphViz embedded in another project

+
    -
  1. Download project Sixth code snapshot. -
  2. -
  3. Inspect and run DataGraph.java. -
  4. +
  5. Download project Sixth code snapshot.
  6. +
  7. Inspect and run DataGraph.java.
-
-

4.2.3 Embedding JavaInspect in your Maven project

-
+
+

5.2.3 Embedding JavaInspect in your Maven project

+

Declare JavaInspect as dependency:

-
<dependencies>
     ...
     <dependency>
@@ -546,7 +681,6 @@ Declare JavaInspect as dependency:
 Add Maven repository to retrieve artifact from:
 

-
<repositories>
     ...
     <repository>
@@ -563,25 +697,8 @@ Add Maven repository to retrieve artifact from:
 
-
-

5 Requirements

-
-

-GraphViz - shall be installed on the computer. -

- -

-On Ubuntu/Debian use: -

-
- -
sudo apt-get install graphviz
-
-
-
-
-
-

6 TO DO

+
+

6 TO DO

Note: Because this is side project (and I have many of them) I can @@ -593,24 +710,19 @@ LOT of cool ideas could be implemented. For intstance:

  • BUG: Should not hide references if there are too many of them to classes if referring classes are not visible anyway because of blacklist/whitelist rules. Basically reference counting should -exclude not visible classes. -
  • +exclude not visible classes.
  • BUG: Orphaned class removal does not work always. There are many -bugs and corner cases to find and fix still. -
  • +bugs and corner cases to find and fix still.
  • BUG: Code is not very readable. Document and refactor for better -maintainability. -
  • +maintainability.
  • FEATURE: Create installable DEB package.
    • Submit it to some Debian developer for integration or become -Debian package maintainer. -
    • -
    -
  • +Debian package maintainer. +
  • FEATURE: Make it modular. That is: central part, an application model could be standalone and serializable. @@ -619,128 +731,81 @@ model could be standalone and serializable.
  • There could be multiple ways to acquire model:
    • By introspecting application via Java reflections (current mode -of operation). -
    • -
    • By parsing java source. (unfinished) -
    • -
    -
  • +of operation). +
  • By parsing java source. (unfinished)
  • +
  • There could be ways to manipulate model:
      -
    • Store/load/compare. -
    • -
    • Trim uninteresting parts. -
    • -
    • Highlight important parts. -
    • -
    -
  • +
  • Store/load/compare.
  • +
  • Trim uninteresting parts.
  • +
  • Highlight important parts.
  • +
  • There could be multiple ways to render model:
      -
    • PNG/SVG (currently implemented) -
    • -
    • PlantUML (TODO) -
    • -
    • Interactive 3D visualization (TODO) -
    • -
    -
  • - - +
  • PNG/SVG (currently implemented)
  • +
  • PlantUML (TODO)
  • +
  • Interactive 3D visualization (TODO)
  • + +
  • FEATURE: Implement (or integrate existing java parser https://javaparser.org/) to be able to produce code visualizations based on source code (in addition to current reflection based -approach). -
  • +approach). -
  • FEATURE: Integarte with PlantUML. -
  • +
  • FEATURE: Integarte with PlantUML.
  • -
  • FEATURE: Add dark theme for generated graphs. -
  • +
  • FEATURE: Add dark theme for generated graphs.
  • -
  • FEATURE: Sort Class fields by alphabet. -
  • +
  • FEATURE: Sort Class fields by alphabet.
  • FEATURE: Visualize also concrete field values so it could be used as -ultra cool runtime logging/debugging framework. -
  • +ultra cool runtime logging/debugging framework.
  • FEATURE: Possibility to visualize structure and data from JVM -snapshot. -
  • +snapshot.
  • FEATURE: Possibility to attach to remote process to visualize -data/structure using JVM debug port and mechanism. -
  • +data/structure using JVM debug port and mechanism. -
  • FEATURE: Possibility to attach to JVM using JVM agent. -
  • +
  • FEATURE: Possibility to attach to JVM using JVM agent.
  • -
  • FEATURE: Possibility to inspect graphs in 3D using Sixth 3D engine. -
  • +
  • FEATURE: Possibility to inspect graphs in 3D using Sixth 3D engine.
  • FEATURE: Possibility to select classes/fields/values to be visualized in some graph query language. For greater flexibility in -comparison to currently supported glob syntax. -
  • +comparison to currently supported glob syntax.
  • FEATURE: Add option to control JavaInspect via JSON or XML config file. For example different graphs for given project could be defined once in plain text config, possibly with the aid of some interactive utility. Then defined graphs could be updated as part of -project build or release process. -
  • +project build or release process.
  • FEATURE: Configurable maven plugin to generate graphs as part of the -project build/release process. -
  • +project build/release process.
    -
    -

    7 See also

    + -
    -
    -

    Author: Svjatoslav Agejenko

    -

    Created: 2021-01-10 P 00:37

    -

    Emacs 26.1 (Org-mode 9.1.9)

    +
    +

    Author: Svjatoslav Agejenko

    +

    Created: 2022-02-20 Sun 20:27

    +

    Validate

    -
    diff --git a/doc/index.org b/doc/index.org index b831a37..7c62a16 100644 --- a/doc/index.org +++ b/doc/index.org @@ -27,6 +27,9 @@ https://github.com/abargnesi/javainspect ** Source code +:PROPERTIES: +:ID: 032b7997-f582-4203-b31a-43ef7b654ed6 +:END: - [[https://www2.svjatoslav.eu/gitweb/?p=javainspect.git;a=snapshot;h=HEAD;sf=tgz][Download latest snapshot in TAR GZ format]] - [[https://www2.svjatoslav.eu/gitweb/?p=javainspect.git;a=summary][Browse Git repository online]] @@ -44,9 +47,9 @@ JavaInspect can be used as a [[id:acf1896a-74b4-4914-acf6-a77075e07f25][standalo [[id:bbeeffc8-3767-440d-8d93-ec9124dd60ee][java library]]. JavaInspect uses primarily Java built-in reflection to discover and visualize any part of Java program. -JavaInspect currently has no GUI, configuration files, embedded -scripting support, direct Maven or Ant integration. See [[id:2ad2889e-6c95-4662-b3f4-2c341fc74522][usage]] to learn -how to instuct Javainspect what to do. +JavaInspect currently has no graphical user interface, configuration +files, embedded scripting support, direct Maven, Gradle or Ant +integration. See [[id:2ad2889e-6c95-4662-b3f4-2c341fc74522][usage]] to learn how to instuct Javainspect what to do. After discovering application structure and optionally filtering out unimportant parts, JavaInspect produces GraphViz dot file that @@ -55,12 +58,11 @@ bitmap graph in PNG or SVG format. Notes: + JavaInspect is developed and tested so far only on GNU/Linux. -+ See: [[https://github.com/pahen/madge][Madge - similar tool for JavaScript]] * Example graphs + A very simple example: - file:example.png + [[file:example.png][file:example-thumbnail.png]] Graph legend: @@ -69,6 +71,31 @@ Notes: + [[https://www3.svjatoslav.eu/projects/sixth-3d/graphs/][See example produced graphs]] for [[https://www3.svjatoslav.eu/projects/sixth-3d/][Sixth 3D - 3D engine project]]. +* Installation +[[http://www.graphviz.org/][GraphViz]] - shall be installed on the computer. + +On Ubuntu/Debian GraphViz can be installed using: +#+BEGIN_SRC sh +sudo apt-get install graphviz +#+END_SRC + +To use JavaInspect via Java API, no further installation is +needed. JavaInspect will be embedded into your project as dependency. +This is described in [[id:bbeeffc8-3767-440d-8d93-ec9124dd60ee][usage via Java API]]. It will expect GraphViz to be +available in the system. + +To use JavaInspect as a commandline tool, JavaInspect source +repository has to be cloned locally: See [[id:032b7997-f582-4203-b31a-43ef7b654ed6][Source code]]. + +Then study and execute installation script: +: commandline launcher/install + +After installation, new commandline tool should be available +: javainspect + +Quick commandline usage help can be viewed by issuing +: javainspect --help + * Usage :PROPERTIES: :ID: 2ad2889e-6c95-4662-b3f4-2c341fc74522 @@ -77,30 +104,31 @@ JavaInspect can be controlled in 2 different ways: + [[id:acf1896a-74b4-4914-acf6-a77075e07f25][as standalone commandline utility]] + [[id:bbeeffc8-3767-440d-8d93-ec9124dd60ee][as embedded Java library via Java API]] -** usage as commandline utility +** Usage as commandline utility :PROPERTIES: :ID: acf1896a-74b4-4914-acf6-a77075e07f25 :END: -To enable commandline support, (study and) execute script: -: commandline launcher/install - -Warning: It was tested only on Debian Stretch linux. - -Available commandline arguments: +*** Available commandline arguments #+BEGIN_VERSE -j (existing files)... JAR file(s) to render. --n (mandatory, string) - Graph name. +-c (existing directories)... + Classpath directories + +-n (string) + Graph name. (default: "graph") --debug Show debug info. +-h, --help + Show commandline usage help. + -k Keep dot file. --h +-ho Hide orphaned classes. -w (one to many strings)... @@ -109,13 +137,50 @@ Available commandline arguments: -b (one to many strings)... Blacklist glob(s). --d (existingdirectory) +-r (one to many strings)... + root class(es). + +-d (existing directory) Target directory. Default is current directory. -t (options: png, svg) Target image type. Default is: svg. #+END_VERSE -** usage via Java API +*** Specifying classes to render +Normal Java application has immense complexity. In addition to code +that was directly written by particular project developers, lots of +functionality is typically added as frameworks or libraries to the +project. In addition there is significant Java standard library. + +Because JavaInspect uses reflection, it does not easily distinguish +between those. In normal situation you would rather want to visualize +only code that was developed specifically for your project and leave +frameworks like Spring etc. out. If you visualize all classes that are +possibly reachable from you project, you will easily get huge and +incomprehensible graph. + +JavaInspect can digest compiled Java classes in 2 modes: +1. Provide list of Jar files. Use *-j* option. +2. Provide list of filesystem directories that can be used as + classpath root. Use *-c* option. + +Currently JavaInspect uses following algorithm to add classes to +rendered graph: + +- All classes that were found in Jar files are added to graph by default. +- None of the classes that were found in filesystem directories are + added to the graph by default (unless explicitly referenced). (TODO: + for consistency it would be better to add them too by default) +- If whitelist is specified (*-w* option) everything that is not + matched by whitelist pattern(s) will be removed from the graph. +- If blacklist is specified (*-b* option) everything that is matched + by blacklist pattern(s) will be removed from the graph. +- Root classes can be specified using *-r* option. Root classes will + be added to the graph. JavaInspect will then try to recursively + discover all classes that were referenced by root class and add + those also to the graph. + +** Usage via Java API :PROPERTIES: :ID: bbeeffc8-3767-440d-8d93-ec9124dd60ee :END: @@ -157,7 +222,7 @@ Control code in general does the following: 5. Render graph. -*** example 1: individually picked objects +*** Example 1: individually picked objects This example demonstrates generating of class graph from hand picked classes and visualizing GraphViz itself. @@ -193,7 +258,7 @@ Result: - Generated DOT file: [[file:JavaInspect.dot][JavaInspect.dot]] - Generated PNG image: [[file:JavaInspect.png][JavaInspect.png]] -*** example 2: GraphViz embedded in another project +*** Example 2: GraphViz embedded in another project 1. Download project Sixth [[https://www2.svjatoslav.eu/gitweb/?p=sixth.git;a=snapshot;h=HEAD;sf=tgz][code snapshot]]. 2. Inspect and run *DataGraph.java*. @@ -226,13 +291,6 @@ Add Maven repository to retrieve artifact from: #+END_SRC -* Requirements -[[http://www.graphviz.org/][GraphViz]] - shall be installed on the computer. - -On Ubuntu/Debian use: -#+BEGIN_SRC sh -sudo apt-get install graphviz -#+END_SRC * TO DO Note: Because this is side project (and I have many of them) I can only contribute few hours per year at average. Any help is welcome. A @@ -310,3 +368,4 @@ LOT of cool ideas could be implemented. For intstance: * See also Similar or alternative solutions: + http://www.class-visualizer.net/ ++ [[https://github.com/pahen/madge][Madge - similar tool for JavaScript]] diff --git a/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java b/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java index 2f8feca..a573a57 100644 --- a/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java +++ b/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java @@ -11,19 +11,20 @@ public class CommandlineConfiguration { public StringParameters whitelistGlob; public StringParameters blacklistGlob; public StringParameters rootClasses; + public NullParameter showHelp; public TargetImageTypeParameter targetImageType; public NullParameter keepDotFile; public DirectoryParameter targetDirectory; + public DirectoryParameters classPaths; public final boolean configurationOk; public NullParameter hideOrphanedClasses; + Parser parser; public static final String DEFAULT_GRAPH_NAME = "graph"; public CommandlineConfiguration(String[] args) { - Parser parser = buildCommandlineParameterParser(); + parser = buildCommandlineParameterParser(); configurationOk = parser.parse(args); - if (!configurationOk) - parser.showHelp(); } public boolean isDebug() { @@ -38,6 +39,11 @@ public class CommandlineConfiguration { .mustExist() .addAliases("-j"); + classPaths = parser.add( + new DirectoryParameters("Classpath directories")) + .mustExist() + .addAliases("-c"); + graphName = parser.add( new StringParameter("Graph name. (default: \"" + DEFAULT_GRAPH_NAME + "\")", DEFAULT_GRAPH_NAME)) .addAliases("-n"); @@ -46,13 +52,16 @@ public class CommandlineConfiguration { new NullParameter("Show debug info.")) .addAliases("--debug"); + showHelp = parser.add(new NullParameter("Show commandline usage help.")) + .addAliases("-h", "--help"); + keepDotFile = parser.add( new NullParameter("Keep dot file.")) .addAliases("-k"); hideOrphanedClasses = parser.add( new NullParameter("Hide orphaned classes.")) - .addAliases("-h"); + .addAliases("-ho"); whitelistGlob = parser.add( new StringParameters("Whitelist glob(s).")) diff --git a/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java b/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java index d4d144a..0c63a55 100644 --- a/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java +++ b/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java @@ -19,9 +19,13 @@ import java.util.jar.JarInputStream; public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException { CommandlineConfiguration configuration = new CommandlineConfiguration(args); - if (!configuration.configurationOk) + if (!configuration.configurationOk) { + configuration.parser.showHelp(); System.exit(1); - + } + + if (configuration.showHelp.isSpecified()) configuration.parser.showHelp(); + getClassGraph(configuration).generateGraph(configuration.graphName.getValue()); if (configuration.isDebug()) @@ -32,7 +36,7 @@ public class Main { List jarFiles = configuration.jarFiles.getValue(); URLClassLoader classLoader = new URLClassLoader( - getFileUrls(jarFiles), + getClasspathUrls(jarFiles, configuration.classPaths.getValue()), configuration.getClass().getClassLoader()); ClassGraph classGraph = new ClassGraph(); @@ -45,7 +49,7 @@ public class Main { classGraph.setKeepDotFile(configuration.keepDotFile.getValue()); - if (configuration.rootClasses.isSpecified()){ + if (configuration.rootClasses.isSpecified()) { // add only selected root classes for (String rootClass : configuration.rootClasses.getValue()) attemptClassAdditionByName(classLoader, classGraph, configuration, rootClass); @@ -64,8 +68,17 @@ public class Main { return classGraph; } - private static URL[] getFileUrls(List jarFiles) { + private static URL[] getClasspathUrls(List jarFiles, List classpathDirectories) { List urls = new ArrayList<>(); + + classpathDirectories.forEach(classpathDirectory -> { + try { + urls.add(classpathDirectory.toURI().toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }); + jarFiles.forEach((File file) -> { try { urls.add(file.toURI().toURL()); @@ -90,7 +103,7 @@ public class Main { System.out.println("Adding class to graph: " + className); try { classGraph.add(loadClassByName(classLoader, className)); - } catch (NoClassDefFoundError e){ + } catch (NoClassDefFoundError e) { if (configuration.isDebug()) System.out.println("Class definition was not found."); // Sometimes referenced classes are not found in the same Jar. -- 2.20.1