[FEATURE] Support child-first class loading for catalog-private dependencies
- Dominant language
- Java
- Stars
- 3.2k
- Forks
- 935
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 298
Description
### Describe the solution
Thanks to @yuqi1129 for pointing out that changing only the non-shared loading branch is insufficient.
A complete solution needs to address both class classification and delegation order. One possible design is an opt-in, package-scoped child-first classloader.
Each catalog package could declare its required strategy through package metadata, for example a `catalog-classloader.properties` resource contained in the catalog JAR:
```
properties
type=child-first
implementation-prefixes=org.apache.gravitino.catalog.example.,org.apache.gravitino.example.internal.
```
Catalogs without this descriptor would continue to use the existing classloader behavior. This preserves backward compatibility and allows each catalog package to own its classloading requirements without adding provider-specific package names to Gravitino Core.
The catalog classloader factory would:
1. Inspect the catalog package for the descriptor.
2. Reject malformed, unsupported, or duplicate descriptors explicitly.
3. Use the existing parent-first IsolatedClassLoader when no descriptor is present.
4. Create a generic child-first isolated classloader when type=child-first is declared.
5. Treat the declared implementation prefix as catalog-private.
The child-first classloader would use the following ownership model.
#### Shared classes
Shared classes include:
- explicitly identified JDK platform APIs;
- logging APIs;
- explicitly configured shared packages;
- Gravitino classes outside the catalog's declared implementation package prefixes.
Catalog implementation package prefixes are treated as private. Ordinary third-party dependencies are also private by default.
#### Private classes
The catalog implementation package and ordinary third-party dependencies are private by default.
Their loading order is:
```
catalog package
↓
shared parent when absent from the catalog package
```
The implementation should use findLoadedClass() and getClassLoadingLock(name) to prevent concurrent duplicate class definitions.
The existing barrier-class behavior can remain unchanged.
#### Resources and SPI
Resource loading should follow the same ownership model:
```
catalog-private resource
↓
parent resource when absent locally
```
When a private resource exists, getResources() should not merge it with parent resources. This is particularly important for META-INF/services/*, where merging providers from different component versions would break package isolation.
#### Lifecycle
The classloader should:
- use a stable parent captured when the component is created;
- use deterministic ordering for private JARs;
- keep the component classloader active as the thread context classloader during component calls;
- prevent closing while component calls are still running;
- prevent reopening after shutdown starts;
- propagate classloader cleanup failures explicitly.
This design avoids changing the behavior of every existing catalog at once. New catalogs, or catalogs that have been verified with child-first isolation, can opt in through their own package descriptor.
If this approach is acceptable, the same generic classloader infrastructure could later be reused by other isolated extension components without introducing catalog- or provider-specific branches.
Contributor guide
Research direction
Start by locating the catalog classloader factory and the existing parent-first IsolatedClassLoader. Read how catalog packages are inspected, how class and resource delegation currently works, and how component lifecycle calls manage their classloader. Done should include an agreed descriptor format, child-first ownership and delegation behavior, and lifecycle handling with explicit tests for malformed metadata, private resources, SPI loading, and shutdown.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, infrastructure
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100