{"id":16686167,"url":"https://github.com/oldratlee/land","last_synced_at":"2025-04-04T14:09:10.380Z","repository":{"id":15305751,"uuid":"18035587","full_name":"oldratlee/land","owner":"oldratlee","description":":dango: Land is a simple Java™ dependency-isolation container via class loader.","archived":false,"fork":false,"pushed_at":"2025-03-31T15:09:21.000Z","size":271,"stargazers_count":154,"open_issues_count":13,"forks_count":50,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-02T05:43:11.508Z","etag":null,"topics":["classloader","classloader-leaks","delegation-mode","java","java-classloader","java-virtual-machine","jvm"],"latest_commit_sha":null,"homepage":"https://github.com/oldratlee/land","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oldratlee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2014-03-23T14:55:14.000Z","updated_at":"2025-02-21T15:36:25.000Z","dependencies_parsed_at":"2024-04-29T16:28:13.014Z","dependency_job_id":"6b85ed7e-4883-4c3f-a2d0-05dd3404bf58","html_url":"https://github.com/oldratlee/land","commit_stats":{"total_commits":104,"total_committers":4,"mean_commits":26.0,"dds":"0.32692307692307687","last_synced_commit":"7e978b3f50066e87a34985bbf5807a618e35fd56"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Fland","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Fland/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Fland/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Fland/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oldratlee","download_url":"https://codeload.github.com/oldratlee/land/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247190253,"owners_count":20898702,"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":["classloader","classloader-leaks","delegation-mode","java","java-classloader","java-virtual-machine","jvm"],"created_at":"2024-10-12T15:04:52.189Z","updated_at":"2025-04-04T14:09:10.359Z","avatar_url":"https://github.com/oldratlee.png","language":"Java","readme":"# \u003cdiv align=\"center\"\u003e🍡 Land\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/oldratlee/land/actions/workflows/ci.yaml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/oldratlee/land/ci.yaml?branch=master\u0026logo=github\u0026logoColor=white\" alt=\"Github Workflow Build Status\"\u003e\u003c/a\u003e\n\u003ca href=\"https://openjdk.java.net/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Java-8+-green?logo=openjdk\u0026logoColor=white\" alt=\"JDK support\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.apache.org/licenses/LICENSE-2.0.html\"\u003e\u003cimg src=\"https://img.shields.io/github/license/oldratlee/land?color=4D7A97\u0026logo=apache\" alt=\"License\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/land/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/oldratlee/land\" alt=\"GitHub Stars\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/land/fork\"\u003e\u003cimg src=\"https://img.shields.io/github/forks/oldratlee/land\" alt=\"GitHub Forks\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/land/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/oldratlee/land\" alt=\"GitHub issues\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/land\"\u003e\u003cimg src=\"https://img.shields.io/github/repo-size/oldratlee/land\" alt=\"GitHub repo size\"\u003e\u003c/a\u003e\n\u003ca href=\"https://gitpod.io/#https://github.com/oldratlee/land\"\u003e\u003cimg src=\"https://img.shields.io/badge/Gitpod-ready--to--code-green?label=gitpod\u0026logo=gitpod\u0026logoColor=white\" alt=\"gitpod: Ready to Code\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n- [:checkered_flag: 概述](#checkered_flag-%E6%A6%82%E8%BF%B0)\n- [:wrench: 功能](#wrench-%E5%8A%9F%E8%83%BD)\n    - [1. `ClassLoader`委托关系的完备配置](#1-classloader%E5%A7%94%E6%89%98%E5%85%B3%E7%B3%BB%E7%9A%84%E5%AE%8C%E5%A4%87%E9%85%8D%E7%BD%AE)\n        - [父子`ClassLoader`委托](#%E7%88%B6%E5%AD%90classloader%E5%A7%94%E6%89%98)\n        - [兄弟`ClassLoader`委托](#%E5%85%84%E5%BC%9Fclassloader%E5%A7%94%E6%89%98)\n    - [2. 常用类加载方式](#2-%E5%B8%B8%E7%94%A8%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%96%B9%E5%BC%8F)\n- [:art: 使用场景](#art-%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF)\n- [:beer: 目标](#beer-%E7%9B%AE%E6%A0%87)\n- [:loudspeaker: 进阶目标](#loudspeaker-%E8%BF%9B%E9%98%B6%E7%9B%AE%E6%A0%87)\n- [:books: 相关资料](#books-%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99)\n    - [已有的基于ClassLoader实现的隔离容器项目](#%E5%B7%B2%E6%9C%89%E7%9A%84%E5%9F%BA%E4%BA%8Eclassloader%E5%AE%9E%E7%8E%B0%E7%9A%84%E9%9A%94%E7%A6%BB%E5%AE%B9%E5%99%A8%E9%A1%B9%E7%9B%AE)\n    - [:microscope: 官方资料](#microscope-%E5%AE%98%E6%96%B9%E8%B5%84%E6%96%99)\n        - [ClassLoader](#classloader)\n        - [Permission](#permission)\n    - [:bookmark: 二手资料](#bookmark-%E4%BA%8C%E6%89%8B%E8%B5%84%E6%96%99)\n        - [ClassLoader](#classloader-1)\n    - [ClassLoader实际应用](#classloader%E5%AE%9E%E9%99%85%E5%BA%94%E7%94%A8)\n    - [安全](#%E5%AE%89%E5%85%A8)\n    - [ClassLoader Memory Leak](#classloader-memory-leak)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n# :checkered_flag: 概述\n\n:point_right: 一个简单的基于`ClassLoader`用于依赖隔离的容器实现。  \n\\# 在`Java`中依赖主要是`Jar`。\n\n依赖容器自然涉及下面的问题：\n\n* 可以从多处加载类，并分配不同的`ClassLoader`\n* `ClassLoader`之间有继承关系  \n`ClassLoader`的继承关系会是一个树\n* 类加载会在上下级`ClassLoader`之间有委托关系，如：\n    * 是否允许在上级`ClassLoader`中查找类。   \n    即是否 **委托**。\n    * 允许在上级`ClassLoader`查找哪些类/包。   \n    即可以配置 **委托** 的粒度。\n    * 只允许在某级`ClassLoader`查找哪些类/包，会忽略这级`ClassLoader`的下级`ClassLoader`中这些类/包，不允许子`ClassLoader`。    \n即必须 **委托**。\n\n\n# :wrench: 功能\n\n## 1. `ClassLoader`委托关系的完备配置\n\n### 父子`ClassLoader`委托\n\n完备委托关系可以先分析只有父子2层`ClassLoader`间委托关系的情况。\n\n某个类的加载在两层父子`ClassLoader`间委托关系，按是否加载排列组合一共有4种情况：\n\n* 父不加载，子不加载【00】    \n可以用来显式禁止某些类的加载。    \n实际应用中应该 **_很少_** 会用到。\n* 父不加载，子加载【01】  \n子自理，父里即使包含了相同的类也不会污染子。实际场景：\n    * 用来`Tomcat`容器自用`Lib`，不会影响到的`Web`应用。\n* 父加载，子不加载【10】  \n一定使用的父的类。实际场景：\n    * `Tomcat`容器的`Servlet` `API`，不允许被`Web`应用改写。\n* 父加载，子加载【11】      \n两者可以加载的情况下，按谁优先分成2个Case：\n    * 父优先。【`Parent-Child`】    \n    即是`Java`缺省的委托策略，代理模式（`Delegation Mode`）。    \n    这个委托策略可以保证`Java`核心库的类型优先加载，`Java`核心库的类的加载工作由引导类加载器来统一完成，保证了`Java`应用所使用的都是同一个版本的`Java`核心库的类，是互相兼容的。\n    * 子优先。【`Child-Parent`】    \n    这种委托关系比较复杂，有引起类版本混乱的风险！:bomb:  \n    实际应用中应该 **_避免_** 这种委托关系。 :no_good:\n\n\u003e :information_source:    \n\u003e 关于子优先【Child-Parent】类版本混乱的风险的细节原因看了后面参考资料就清楚了，这里只说一个简单例子：    \n\u003e 子里有类`Wheel`；父里有类`Car`、`Wheel`；类`Car`引用了类`Wheel`。    \n\u003e 子加载类`Car`里通过实际是父来加载（子中没有这个类），返回的`Car`所引用`Wheel`是用`Car`的`ClassLoader`即父来加载。    \n\u003e 子中直接使用`Wheel`时，由子来加载（子里有`Wheel`类）。    \n\u003e 结果`Car`引用的类`Wheel`和子直接使用的类`Wheel`的`ClassLoader`不同，即类型不兼容，看起来正确的赋值会抛出的`ClassCastException`！\n\n上面【11】的情况分成2个子Case，合起来一共有5种情况。\n\n委托关系可以统一描述成：\n\n1. `None`\n2. `Child-Only`\n3. `Parent-Only`\n4. `Parent-Child`\n5. `Child-Parent`\n\n按上面说明的2层委托关系约定，嵌套推广即可得到 包含 **任意层**`ClassLoader`的完备委托关系。:sparkles:\n\n### 兄弟`ClassLoader`委托\n\n父子`ClassLoader`由于树状的单继承关系，委托关系比较单一。\n要实现复杂的代理关系，兄弟`ClassLoader`之间代理可以简化。\n\n举个场景，多个中间件如`RPC`、`Message`等，要需要把部分类代理给应用`ClassLoader`，如果就使用父子代理，结果会是这样：\n\n```bash\nSystem ClassLoader\n    |\n    V\nRPC ClassLoader\n    |\n    V\nMessage ClassLoader\n    |\n    V\nApp ClassLoader\n```\n\n上面问题是，`RPC ClassLoader`和`Message ClassLoader`之间的父子关系不符合实际关系（`RPC ClassLoader`和`Message ClassLoader`之间并不需要父子代理）。\n\n更合理些的代理关系是：\n\n```bash\n                  System ClassLoader\n                /         |         \\\n              /           |          \\\n            V             V           V\nRPC ClassLoader -\u003e App ClassLoader \u003c- Message ClassLoader\n```\n\n即`RPC ClassLoader`和`Message ClassLoader`作为`App ClassLoader`的兄弟`ClassLoader`并代理。\n\n## 2. 常用类加载方式\n\n* 加载本地类目录或`Jar`文件\n* 加载本地有类目录或`Jar`文件的目录\n* 加载网络上的类    \n这个功能应该很少使用 :stuck_out_tongue_winking_eye: ，为了功能完整而说明。\n* 加密类工具/加载加密的类    \n这个功能应该很少使用 :stuck_out_tongue_closed_eyes: ，为了功能完整而说明。\n\n# :art: 使用场景\n\n1. 在一个`JVM`中部署多个应用，但应用依赖不互相影响。    \n这样是提高 **系统利用率** 的一种方式。\n2. 把平台级的二方库从应用中隔离出来，由架构部门统一升级。这样做的原因是：\n    - 平台级二方库如果有`Bug`影响面广，有统一的升级的需求。\n    - 平台级二方库升级使用面广，升级困难。\n\n\u003e :information_source:  \n\u003e 上面的部署方式中，依赖容器的引入对于应用的开发应该是 **透明** 的。\n\n# :beer: 目标\n\n* 给出类加载委托情况的完备说明\n* 给出类加载委托规则的规范描述\n* 给出类加载委托规则的规范描述的自己的一个描述格式  \n对于这个项目会优先使用`Properties`来描述，简单够用。\n* 说明`Java`的`ClassLoader`的用途和限制\n* 给出`ClassLoader`使用和实现的原则\n* `ClassLoader`使用和实现容易出错的地方\n* 整理出使用了`ClassLoader`的常见框架\n* 说明这些框架中`ClassLoader`的实现方法及其使用契约\n* 给出`ClassLoader`实现方法及其使用契约的最佳实践\n\n# :loudspeaker: 进阶目标\n\n* `Web`容器集成\n* 实现`OSGi`规范    \n这个也可以用来验证实现是否面向编程友好\n\n# :books: 相关资料\n\n## 已有的基于ClassLoader实现的隔离容器项目\n\n- [`jboss-modules`](https://github.com/jboss-modules/jboss-modules)  \n    JBoss Modules is a standalone implementation of a modular (non-hierarchical) class loading and execution environment for Java.\n- [`sofa-jarslink`](https://github.com/sofastack/sofa-jarslink)  \n    Jarslink is a sofa ark plugin used to manage multi-application deployment\n\n## :microscope: 官方资料\n\n### ClassLoader\n\n* [The Java Language Specification](http://docs.oracle.com/javase/specs/jls/se7/html/index.html)的[第12章 Execution](http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html)和[The Java Virtual Machine Specification](http://docs.oracle.com/javase/specs/jvms/se7/html/index.html)的[第5章 Loading, Linking, and Initializing](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html)    \n详细介绍了`Java`类的加载、链接和初始化。    \n不同`Java`版本的语言和`JVM`规范在\u003chttp://docs.oracle.com/javase/specs/\u003e\n* [Multithreaded Custom Class Loaders in Java SE 7](http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html)，`JDK` 7修复了`ClassLoader`的死锁问题。    \n这个问题在`JDK 7`之前的版本中一直存在。平时使用中确实不容易碰到，但在线上应用复杂和高压力场景中有实际观察到过。    \n这篇文档给出问题的原因及其修复方法。\n* `Java`命令行选项`-verbose:class`可以在加载类时显示相关信息。    \n完整`Java`命令行选项参见： \u003chttp://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html\u003e\n* [Java API doc - ClassLoader](http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html)\n* [Understanding Extension Class Loading](http://docs.oracle.com/javase/tutorial/ext/basics/load.html)\n* `Sun` `JDK`用于启动应用的[`Laucher`实现类](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/misc/Launcher.java)。    \n注： `sun.misc.Launcher`类没有在`JDK`附带的`src.zip`中，因为是`JDK`具体实现部分（厂商相关），可以在`JDK`源码中找到这个`Java`类。    \n`Sun`的`JDK`的源码下载在[这里](http://download.java.net/openjdk/jdk7/)，厂商相关`Java`类在目录`jdk/src/share/classes`下。\n* `Laucher`类中包含了`Java`除`BootstrapClassloader`（是用本地代码`C/C++`来实现）外另2个`Buildin` `ClassLoader`类的实现：\n    * [`ExtClassLoader`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/misc/Launcher.java#Launcher.ExtClassLoader)\n    * [`AppClassLoader`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/misc/Launcher.java#Launcher.AppClassLoader)\n\n### Permission\n\n* [Permissions in JDK 7](http://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html)\n* [Permissions in JDK 6](http://docs.oracle.com/javase/6/docs/technotes/guides/security/permissions.html)\n\n## :bookmark: 二手资料\n\n### ClassLoader\n\n* [IBM DeveloperWorks - 深入探讨Java类加载器](https://www.ibm.com/developerworks/cn/java/j-lo-classloader/)。一篇非常不错的`ClassLoader`的介绍文章，并且对比介绍了\n    * `Java` `SPI`的类加载策略。包含`JDBC`和`JAXP`为代表的2种方式。\n    * `Tomcat`的类加载策略。\n    * `OSGi`的类加载策略。\n* [The basics of Java class loaders](http://www.javaworld.com/article/2077260/learn-java/the-basics-of-java-class-loaders.html)   \n`1996`年(`Java 1`的年代)的一篇老文章，其中描述功能现在可以通过`Java 2`提供的[`java.net.URLClassLoader`](http://docs.oracle.com/javase/7/docs/api/java/net/URLClassLoader.html)方便的完成。    \n但实现复杂自定义`ClassLoader`的流程是一样的，文章给出了实现自定义`ClassLoader`\n    * 要覆盖的`ClassLoader`关键方法\n    * 要遵循的基本约定\n    * 要注意的安全问题\n* [IBM DeveloperWorks - Understanding the Java ClassLoader](http://www6.software.ibm.com/developerworks/education/j-classloader/j-classloader-a4.pdf)\n* [IBM DeveloperWorks - Java programming dynamics, Part 1: Java classes and class loading](https://www.ibm.com/developerworks/library/j-dyn0429/)    \n中文版在：[Java编程的动态性，第 1 部分: 类和类装入](http://www.ibm.com/developerworks/cn/java/j-dyn0429/)    \n[Java programming dynamics series](http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=Java+dynamics)，这个系列的中文版[Java编程的动态性](https://www.ibm.com/developerworks/cn/views/java/libraryview.jsp?type_by=%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0\u0026view_by=search\u0026search_by=Java+%E7%BC%96%E7%A8%8B%E7%9A%84%E5%8A%A8%E6%80%81%E6%80%A7)\n* [onjava.com - Internals of Java Class Loading](http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html)\n* [IBM DeveloperWorks - Demystifying class loading problems series](http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=demystifying+class+loading+problems)\n* [IBM Java Diagnostics Guide - Class loading](http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp?topic=%2Fcom.ibm.java.doc.diagnostics.50%2Fdiag%2Funderstanding%2Fclass_loader.html)\n* [Getting Started with Javassist - Class Loader](http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/tutorial/tutorial.html#load)\n* [Sheng Liang and Gilad Bracha, \"Dynamic Class Loading in the Java Virtual Machine\"](http://kenwublog.com/docs/Dynamic+Class+Loading+in+the+Java+Virtual+Machine.pdf)    \nACM OOPSLA'98, pp.36-44, 1998.\n* [Wikipedia - Java Classloader](http://en.wikipedia.org/wiki/Java_Classloader)\n* [Class.forName() vs ClassLoader.loadClass() - which to use for dynamic loading?](http://stackoverflow.com/questions/8100376/class-forname-vs-classloader-loadclass-which-to-use-for-dynamic-loading)\n\n## ClassLoader实际应用\n\n* [Understanding WebLogic Server Application Classloading](http://docs.oracle.com/cd/E24329_01/web.1211/e24368/classloading.htm)\n* [The Apache Tomcat 5.5 Servlet/JSP Container - Class Loader HOW-TO](http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html)：详细介绍了`Tomcat` 5.5中的类加载器机制。\n* [OSGi Service Platform Core Specification](http://www.osgi.org/Specifications/HomePage)\n\n## 安全\n\n* [IBM DeveloperWorks - Java安全模型介绍](http://www.ibm.com/developerworks/cn/java/j-lo-javasecurity/)\n* [IBM DeveloperWorks - Java 授权内幕](http://www.ibm.com/developerworks/cn/java/j-javaauth/)  \n更多内容参见：[IBM DeveloperWorks - Java安全专题](https://www.ibm.com/developerworks/cn/java/j-security/)\n* [Java Security - Chapter 3. Java Class Loaders](http://docstore.mik.ua/orelly/java-ent/security/ch03_01.htm)\n\n## ClassLoader Memory Leak\n\n* [Classloader leaks: the dreaded \"java.lang.OutOfMemoryError: PermGen space\" exception](http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html)\n* [How to fix the dreaded \"java.lang.OutOfMemoryError: PermGen space\" exception (classloader leaks)](http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html)\n* [IBM DeveloperWorks - Diagnosis of Java class loader memory leaks](http://www.ibm.com/developerworks/webservices/library/ws-javaclass/index.html)\n* [Reloading Java Classes 201: How do ClassLoader leaks happen?](http://zeroturnaround.com/rebellabs/rjc201/)\n* [Classloader-Related Memory Issues](http://javabook.compuware.com/content/memory/problem-patterns/class-loader-issues.aspx)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foldratlee%2Fland","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foldratlee%2Fland","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foldratlee%2Fland/lists"}