{"id":22295777,"url":"https://github.com/danielfernandez/test-dynamic-class-loading","last_synced_at":"2025-03-25T22:34:02.817Z","repository":{"id":146695452,"uuid":"90303175","full_name":"danielfernandez/test-dynamic-class-loading","owner":"danielfernandez","description":"Test repository for a weird class loading behaviour","archived":false,"fork":false,"pushed_at":"2017-05-05T20:48:31.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-30T19:49:05.626Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danielfernandez.png","metadata":{"files":{"readme":"README.markdown","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-04T19:43:22.000Z","updated_at":"2017-05-04T19:48:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"3e521548-568f-4016-a58f-1d0770383c2a","html_url":"https://github.com/danielfernandez/test-dynamic-class-loading","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielfernandez%2Ftest-dynamic-class-loading","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielfernandez%2Ftest-dynamic-class-loading/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielfernandez%2Ftest-dynamic-class-loading/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielfernandez%2Ftest-dynamic-class-loading/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danielfernandez","download_url":"https://codeload.github.com/danielfernandez/test-dynamic-class-loading/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245554876,"owners_count":20634628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-03T17:43:09.350Z","updated_at":"2025-03-25T22:34:02.782Z","avatar_url":"https://github.com/danielfernandez.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Test for unexpected behaviour in JVMs dynamic class loading\n\nStackOverflow ticket (including solution): http://stackoverflow.com/questions/43792289/unexpected-behaviour-in-jvm-class-loading-classnotfoundexception-before-the-cla/43793110\n\nTested with **Java 1.8.0_131**.\n\nThis test consists of three artifacts:\n\n   * A library called `libone` containing a class called `ParentClassFromLibOne`.\n   * A library called `libtwo` containing a class called `ParentClassFromLibTwo`, which extends from \n   `ParentClassFromLibOne`. This library has a (`compile`-scope) dependency on `libone`.\n   * An application module, with classes `DynamicClassLoadingAppOK` and\n   `DynamicClassLoadingAppKO` showing how a change in the type of a method\n   parameter changes the result from the expected behaviour for dynamic\n   class loading to an unexpected one. This module has a (`compile`-scope)\n   dependency on `libone` and a (`provided`-scope) dependency on `libtwo`.\n\nCode of `ParentClassFromLibOne`:\n\n```java\npublic class ParentClassFromLibOne {\n\n    public String message() {\n        return \"Message from Parent class at LibOne\";\n    }\n\n}\n```\n\nCode of `ChildClassFromLibTwo`:\n\n```java\npublic class ChildClassFromLibTwo extends ParentClassFromLibOne {\n\n    @Override\n    public String message() {\n        return \"Message from Child class at LibTwo\";\n    }\n\n}\n\n```\n\nCode of the *app* class in which the behaviour is as expected\nand the `System.out.println` call at the end is executed:\n\n```java\npublic class DynamicClassLoadingAppOK {\n\n    /*\n     * THIS VERSION WORKS OK, BECAUSE showMessage RECEIVES THE CHILD CLASS AS A PARAMETER\n     */\n\n\n    // If this method received ParentClassFromLibOne, we would have a ClassNotFoundException\n    private static void showMessage(final ChildClassFromLibTwo obj) {\n        System.out.println(obj.message());\n    }\n\n\n    public static void main(final String[] args) throws Throwable {\n\n        try {\n\n            final ChildClassFromLibTwo obj = new ChildClassFromLibTwo();\n            showMessage(obj);\n\n        } catch (final Throwable ignored) {\n            // ignored, we just wanted to use it if it was present\n        }\n\n        System.out.println(\"This is displayed perfecty fine... as expected.\");\n\n    }\n\n}\n```\n\nCode of the *app* class in which the behaviour obtained is\nunexpected and the `System.out.println` call at the end is\nnever executed (a `ClassNotFoundException` is thrown instead).\nNote the only difference is the type of the parameter of the\n`showMessage(...)` method.\n\n```java\npublic class DynamicClassLoadingAppKO {\n\n    /*\n     * THIS VERSION DOES NOT WORK, A ClassNotFoundException IS THROWN BEFORE EVEN EXECUTING main()\n     */\n\n\n    // If this method received ChildClassFromLibTwo, everything would work OK!\n    private static void showMessage(final ParentClassFromLibOne obj) {\n        System.out.println(obj.message());\n    }\n\n\n    public static void main(final String[] args) throws Throwable {\n\n        try {\n\n            final ChildClassFromLibTwo obj = new ChildClassFromLibTwo();\n            showMessage(obj);\n\n        } catch (final Throwable ignored) {\n            // ignored, we just wanted to use it if it was present\n        }\n\n        System.out.println(\"This should be displayed, but no :(\");\n\n    }\n\n}\n```\n\n### How to test\n\nFirst install the two libraries:\n\n```\n$ cd libone\n$ mvn clean compile install\n$ cd ..\n\n$ cd libtwo\n$ mvn clean compile install\n$ cd ..\n```\n\nThen compile and execute the app:\n\n```\n$ cd app\n$ mvn clean compile\n$ mvn exec:java -Dexec.mainClass=com.github.danielfernandez.testdynamicclassloading.app.DynamicClassLoadingAppOK\n$ mvn exec:java -Dexec.mainClass=com.github.danielfernandez.testdynamicclassloading.app.DynamicClassLoadingAppKO\n```\n\nThe first app class executes fine, the second one throws:\n\n```\njava.lang.NoClassDefFoundError: com/github/danielfernandez/testdynamicclassloading/libtwo/ChildClassFromLibTwo\n\tat java.lang.Class.getDeclaredMethods0(Native Method)\n\tat java.lang.Class.privateGetDeclaredMethods(Class.java:2701)\n\tat java.lang.Class.privateGetMethodRecursive(Class.java:3048)\n\tat java.lang.Class.getMethod0(Class.java:3018)\n\tat java.lang.Class.getMethod(Class.java:1784)\n\tat org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:281)\n\tat java.lang.Thread.run(Thread.java:745)\nCaused by: java.lang.ClassNotFoundException: com.github.danielfernandez.testdynamicclassloading.libtwo.ChildClassFromLibTwo\n\tat java.net.URLClassLoader.findClass(URLClassLoader.java:381)\n\tat java.lang.ClassLoader.loadClass(ClassLoader.java:424)\n\tat java.lang.ClassLoader.loadClass(ClassLoader.java:357)\n\t... 7 more\n```\n\nNote a `ClassNotFoundException` is actually thrown in both cases, but in the `OK` one it happens when the\n`ChildClassFromLibTwo` is loaded when a new instance of such class is created, so it is correctly caught\nby the `catch (Throwable t)` block and execution can go on.\n\nNevertheless, in the `KO` class the `ClassNotFoundException` is thrown **before executing `main()`**, apparently when the\n`DynamicClassLoadingAppKO` class itself is loaded, and therefore outside of the `try...catch`, so no code is\nexecuted at all.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielfernandez%2Ftest-dynamic-class-loading","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielfernandez%2Ftest-dynamic-class-loading","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielfernandez%2Ftest-dynamic-class-loading/lists"}