Backend Development 32 min read

Analysis of JD's Middle‑Platform Evolution and the Underlying Matrix Technical Framework

This article examines JD's practical implementation of middle‑platform (中台) evolution, detailing the design rationale, the Matrix support framework, hot‑deployment mechanisms, class‑loader isolation, and business‑identity principles to illustrate how the architecture improves delivery speed and modularity.

JD Retail Technology
JD Retail Technology
JD Retail Technology
Analysis of JD's Middle‑Platform Evolution and the Underlying Matrix Technical Framework

This article explores JD's real‑world adoption of a middle‑platform (中台) architecture, analyzing the evolution mindset and the underlying technical support framework named Matrix.

The document is organized into six main parts: a preface, an analysis of the underlying support framework, the design principles of front‑end hot‑deployment, the front‑middle isolation principle, the front‑end business‑identity design, and concluding reflections.

Unlike traditional monolithic or micro‑service constructions, the middle‑platform introduces a distinct front‑end role that consumes standardized capabilities exposed by the platform; from an external view the system appears as a single functional delivery, while internally the platform and front‑end responsibilities are clearly separated to accelerate delivery.

Delivery speed, rather than the sheer number of platform capabilities or front‑end extensions, is presented as the primary success metric for middle‑platform initiatives.

The Matrix framework aims to partition business domains, model and abstract them, isolate core logic and high‑frequency personalized logic, and delegate the personalized part to front‑end teams, thereby stabilizing the platform core while allowing parallel front‑end development.

Although the framework is applied across various JD systems (APP front‑ends, web front‑ends, back‑end services, data‑algorithm platforms, reporting platforms, etc.), the author acknowledges that it may not fit every scenario and that tool diversity is inevitable.

The implementation path typically follows: middle‑platform capability upgrade → open standard extensions → front‑end consumes extensions for personalization → integrated release, with two integration modes—manual semi‑automatic and fully automatic—where the latter relies on hot‑deployment of front‑end packages into the platform.

Hot‑deployment is realized through two data‑flow chains. The “push” chain is triggered by console actions (publish, take‑effect, unload, alive) that send real‑time change messages via DUCC to SDK‑enabled containers, which then download and load the front‑end package (e.g., PublishActionImpl , TakeEffectActionImpl , UnloadActionImpl , DoAliveActionImpl ). The “pull” chain occurs when a container is scaled out; the SDK detects the new instance, fetches the latest effective package from the remote file server, and performs hot‑loading.

Each chain suits different scenarios: the push chain for latency‑critical operations such as gray releases or rollbacks, and the pull chain for less time‑sensitive cases like container expansion or when push delivery is impractical.

The author discusses why a single‑chain solution is insufficient, illustrating the trade‑offs of using only push (issues with rapid container discovery) or only pull (delayed reaction to console actions), and concludes that a hybrid approach balances cost and performance.

Practical hot‑deployment considerations include controlling large‑scale expansion pace to avoid file‑server overload and limiting front‑end package size to reduce network and I/O impact.

Class isolation is achieved by assigning distinct ClassLoaders to the platform and front‑end packages. The front‑end uses a custom BizClassLoader that deliberately breaks the traditional parent‑delegation model, allowing front‑end code to access platform classes while preventing the platform from accessing front‑end classes. Key code excerpts are shown below:

protected Class
loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        Class
c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) { }
            if (c == null) {
                long t1 = System.nanoTime();
                c = findClass(name);
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) resolveClass(c);
        return c;
    }
}
public class BizClassLoader extends URLClassLoader {
    public BizClassLoader(URL[] urls) { super(urls); }
    protected Class
loadClass(String name, boolean resolve) throws ClassNotFoundException {
        Class
clazz = findLoadedClass(name);
        if (clazz != null) return clazz;
        try {
            ClassLoader jdkClassLoader = ClassLoaderFactory.getJDKClassLoader();
            clazz = jdkClassLoader.loadClass(name);
            if (clazz != null) return clazz;
        } catch (ClassNotFoundException ignored) {}
        if (ExportClassManager.match(name)) {
            clazz = ClassLoaderFactory.getInternalClassLoader().loadClass(name);
            if (clazz != null) return clazz;
        }
        try { clazz = findClass(name); } catch (ClassNotFoundException ignored) {}
        if (clazz == null) clazz = ClassLoaderFactory.getInternalClassLoader().loadClass(name);
        return clazz;
    }
    protected Class
findClass(String name) throws ClassNotFoundException { return super.findClass(name); }
}

Business identity (业务身份) is another core concept. Front‑end packages can define their own parser class (manual mode) or rely on the platform’s auto‑parser (auto mode). The platform ranks identities by priority, version, and code; the first matching identity determines which front‑end logic executes. Risks include heavy identity‑matching logic causing performance degradation and unhandled Throwable exceptions aborting subsequent executions.

Best practices suggested include using distinct package namespaces for front‑end and platform code, limiting the scope of platform‑exposed packages, and enforcing lightweight identity logic to avoid overlapping business rules.

In conclusion, the article encourages continuous reflection on how underlying technical details—such as hot‑deployment pipelines, class‑loader strategies, and business‑identity design—serve the broader goal of delivering reliable, modular services.

Javamicroservicesmiddlewareplatform architectureClassLoaderPaaSHot Deployment
JD Retail Technology
Written by

JD Retail Technology

Official platform of JD Retail Technology, delivering insightful R&D news and a deep look into the lives and work of technologists.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.