A unified scheduling method and device for a multi-language modular application system

CN122985178APending Publication Date: 2026-10-27卜昕宇
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202611162948.6
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2026-08-03
Publication Date
2026-10-27

Smart Images

  • Figure CN122985178A_ABST
    Figure CN122985178A_ABST
Patent Text Reader

Abstract

The application discloses a unified scheduling method and device for a multi-language modular application system. A language type is determined through a description file and a directory content dual determination module. A GroovyClassLoader instance is reserved when a JVM internal compilation loading type module is disabled to eliminate a hot reloading type conflict exception. MyBatis and MyBatis-Plus cache residues are reflected and removed in batches when unloading. Unified routing registration and a state machine are matched to realize unified scheduling and full life cycle management of multi-language modules.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This application relates to the field of computer software technology, specifically to a unified scheduling method and apparatus for multilingual modular application systems. Background Technology

[0002] As enterprise information system architectures evolve towards modularity and microservices, a platform often needs to support business modules developed using different programming languages. For example, core business logic might be written in Java or Kotlin, reporting and data analysis functions might be implemented in Python, high-performance computing modules might be written in C, and rapidly iterating business rules might be written in Groovy scripts. The loading mechanisms, compilation methods, runtime environments, and lifecycle management of modules in different languages ​​are fundamentally different, necessitating the design and maintenance of a separate module management subsystem for each language on the platform.

[0003] In existing technologies, Groovy modules are typically hot-compiled and loaded within the JVM via GroovyClassLoader, Java / Kotlin modules are usually loaded as JAR files via URLClassLoader in an isolated manner, while Python and C language modules require launching independent operating system subprocesses to run. These three loading mechanisms are independent at the underlying technology level and lack a unified scheduling framework to integrate them. Existing solutions often use hard-coded language type judgment logic, assigning modules to their respective language loaders, resulting in scattered routing registration, inconsistent state management, and cross-language modules being unaware of each other's lifecycle changes.

[0004] In existing technologies, some task scheduling frameworks (such as xxl-job) provide a Groovy GLUE mode, allowing Groovy scripts to be written in a web interface and dynamically compiled and executed using GroovyClassLoader. However, the GroovyClassLoader usage pattern of these frameworks is "load-execute-release," creating a new GroovyClassLoader instance for each execution and releasing it immediately after execution. Its design goal is to complete the scheduling and execution of a single scheduled task, rather than maintaining the entire lifecycle of a module (installation, activation, deactivation, uninstallation, and cleanup). Furthermore, frameworks like xxl-job only support Groovy as an extension language and lack unified management capabilities for multi-language modules (such as Python, C language subprocess modules, and Java JAR package modules), failing to provide unified cross-language route registration and module state management.

[0005] For Java JAR modules, the OSGi specification provides a module lifecycle management framework, but it only applies to pre-compiled Java Bundles and cannot simultaneously manage source code modules dynamically compiled via GroovyClassLoader and Python / C language modules running as external processes. For external language modules like Python, existing solutions typically require developers to encapsulate them as independent microservices and manage them using container orchestration tools like Docker, which introduces additional operational complexity and network communication overhead. Therefore, to date, no solution has been able to unify the loading, routing, and lifecycle management of these three heterogeneous modules—Groovy / JVM compiled modules, Java JAR classpath isolated modules, and external process modules—into a single scheduling framework within a single application platform.

[0006] Furthermore, for Groovy modules compiled and loaded within the JVM, when dynamically compiled using GroovyClassLoader, each reload of the module creates a new ClassLoader instance, which can lead to GroovyCastException type conversion exceptions due to inconsistencies in class metadata (bytecode version number, class unique identifier, etc.) within the underlying JVM. Additionally, if the cached data remaining in the JVM memory of persistence frameworks like MyBatis is not cleared after the module is unloaded, it can cause memory leaks and cross-module data interference issues during long-term operation.

[0007] Specifically, the root cause of GroovyCastException lies in the fact that the JVM uses a tuple of "fully qualified class name + class loader instance" as the unique identifier for a class during class loading. The method signatures generated by Groovy's dynamic compilation include Groovy runtime-specific types (such as groovy.lang.Closure), which are also bound to the GroovyClassLoader instance that created them. When a module is reloaded, if the old GroovyClassLoader is discarded and a new instance is created, although the fully qualified class names are the same after compilation, the JVM treats them as completely different types because their class loader instances are different. At this point, if references to instances of the old type still exist in the system (such as variables captured in registered route handler closures), the JVM will throw a GroovyCastException during type conversion or method calls due to the mismatch between the old and new type class loaders. This error manifests as intermittent type conversion failures at runtime. Traditional solutions (such as restarting the JVM) are too costly, while simple ClassLoader replacement solutions cannot fundamentally solve the problem.

[0008] Therefore, how to provide a unified scheduling method for multi-language modular application systems, integrate heterogeneous language loading strategies into the same scheduling framework, and solve the problems of type conflict exceptions and cache residues of compiled and loaded modules within the JVM has become an urgent technical problem to be solved. Summary of the Invention

[0009] This application provides a unified scheduling method and apparatus for multi-language modular application systems, aiming to solve the problems of independent loading mechanisms for different language modules and the lack of a unified scheduling framework in existing technologies. This application integrates three heterogeneous technical approaches—GroovyClassLoader dynamic compilation, URLClassLoader JAR isolated loading, and independent process management—into an inseparable scheduling framework through a coupled architecture consisting of an automatic module type detection module, three heterogeneous language managers, a unified routing registry center, and a unified module state machine. It also solves the type conflict exceptions during hot reloading of compiled and loaded modules within the JVM and the MyBatis cache residue problem after module unloading.

[0010] Firstly, this application provides a unified scheduling device for multi-language modular application systems, comprising: an automatic module type detection module, used to scan the module directory, parse the description files of each module, and automatically determine the language type of the module through a dual determination mechanism combining the declaration fields of the description files and the characteristics of the directory content; wherein, when Groovy or Kotlin source code files exist in the module directory, the module is determined to be JVM in-process compiled and loaded and distributed to the first language manager; when JAR archive files exist, the module is determined to be JVM classpath isolated loaded and distributed to the second language manager; when executable file entry declarations exist, the module is determined to be external process loaded and distributed to the third language manager; the first language manager is used to dynamically compile the source code through GroovyClassLoader, and retain the GroovyClassLoader instance when the module is deactivated to eliminate type conflict exceptions during reinstallation; the second language manager is used to load JAR packages through URLClassLoader and instantiate the module entry class; the third language manager is used to start an independent operating system subprocess, allocate a dynamic port number, and communicate via HTTP. Once the health check probe confirms readiness, the agent registers the route; a unified route registry center is used to receive HTTP route registration requests from various language managers, uniformly maintain the route mapping table for all language type modules, and support exact matching, named path parameter matching, and wildcard path matching; a unified module state machine is used to provide the same set of lifecycle state definitions and state transition rules for modules of all language types.

[0011] Furthermore, the device also includes a module cache cleanup module, which is used to batch clear cache residues generated by MyBatis and MyBatis-Plus persistence layer frameworks during module runtime through a systematic mechanism that combines maintaining a static configuration mapping table with a general reflection framework after the compiled and loaded modules in the JVM have been unloaded. The clearing items cover key cache structures such as mappedStatements, resultMaps, caches, and parameterMaps in MyBatis Configuration, and TABLE_INFO_CACHE and COLUMN_CACHE_MAP in MyBatis-Plus.

[0012] Secondly, this application provides a unified scheduling method for multilingual modular application systems, including: Automatic module type detection (S1): Scan the module directory, automatically determine the language type based on the characteristics of the directory content, and distribute the module accordingly; Multi-strategy loading and route registration (S2): For JVM in-compile loaders, GroovyClassLoader is used to dynamically compile and retain instances; for JVM classpath isolated loaders, URLClassLoader is used to load JARs; for external process loaders, child processes are started and readiness is confirmed through HTTP health checks, and all are uniformly registered with the route registry center. Unified route matching (S3): At runtime, routes are searched based on the priority of exact match, named path parameter match, and wildcard path match; Unified State Management (S4): All language type modules submit state transition requests to the state machine through a unified interface.

[0013] The beneficial effects of the technical solution provided in this application are as follows: (1) Through automatic module type detection and a unified scheduling architecture of three language managers, the four heterogeneous loading mechanisms of Groovy's GroovyClassLoader loading, Java / Kotlin's URLClassLoader loading, and C / Python's subprocess loading are integrated into the same scheduling framework, and the differences in the implementation language of the module are not perceived at runtime. (2) By using the GroovyClassLoader retention strategy, the ClassLoader instance is retained and not released when the module is stopped, eliminating the GroovyCastException type conversion exception caused by repeated creation of class loaders in Groovy hot reloading scenarios, so that the module can be safely enabled and disabled repeatedly without restarting the main system. (3) Through the batch reflection cache cleanup mechanism, all known cache structures of MyBatis Core and MyBatis-Plus are systematically covered to achieve zero-residual hot unloading after module unloading; (4) Through the three-level matching strategy of precise matching, path parameter and wildcard matching of the unified route registry center, a unified route parsing entry point is provided for different language modules, and the caller does not need to be aware of the module language; (5) It should be noted that this solution is not a simple parallel arrangement of three language loaders, but rather a coupled architecture consisting of automatic module type detection, a unified routing registry, and a unified module state machine, which inseparably organizes the three heterogeneous loaders into a whole. The unified routing registry in this solution is fundamentally different from common API gateways (such as Nginx and Kong): API gateways are independent network middleware that forward requests outside the process, while the unified routing registry in this solution runs inside the application process, performs application-level route matching based on module identifiers, and the caller obtains the route handler through a unified interface, completing request distribution within the same JVM process without generating additional network serialization / deserialization overhead. Attached Figure Description

[0014] Figure 1 A schematic diagram of the structure of the unified scheduling device for multilingual modules provided in the embodiments of this application.

[0015] Figure 2 This is a flowchart illustrating the automatic detection of module types provided in an embodiment of this application.

[0016] Figure 3 This is a schematic diagram illustrating the multi-policy loading and route registration process provided in an embodiment of this application.

[0017] Figure 4 This is a schematic diagram of the unified route matching process provided in an embodiment of this application.

[0018] Figure 5 A flowchart illustrating the GroovyClassLoader retention strategy provided in this application embodiment. Detailed Implementation

[0019] To make the objectives, technical solutions, and advantages of this application clearer, the application will now be described in further detail with reference to the accompanying drawings.

[0020] It should be noted that, in the embodiments of this application, the term "module" refers to an independent business functional unit organized in the form of folders. Each module contains a module description file (module.json), a backend code directory (backend / ), and optional multiple frontend code directories (frontend / , etc.). The module description file declares the module's unique identifier (key), name, version, language type, and the services and dependencies provided to the outside world.

[0021] Example 1: Structure of the Unified Scheduling Device Figure 1 The structure of the multilingual module unified scheduling device provided in an embodiment of this application is illustrated. The device includes: The module type automatic detection module 10 is connected to the first language manager 20, the second language manager 30, and the third language manager 40.

[0022] First Language Manager 20 is used to manage JVM-compiled and loaded modules (in Groovy / Kotlin source code form).

[0023] Second Language Manager 30 is used to manage JVM classpath-isolated loaded modules (in JAR package form).

[0024] The third language manager 40 is used to manage externally loaded modules (C compiled binaries or Python scripts).

[0025] The unified routing registry 50 communicates with the first, second, and third language managers.

[0026] The unified module state machine 60 communicates with the first, second, and third language managers.

[0027] The module cache cleanup module 70 is connected in communication with the first language manager 20.

[0028] When the system starts, the automatic module type detection module 10 scans the module directory at the same level as the platform base and reads the module description file of each module one by one. First, it reads the language type field declared in the description file; if the value of this field is not empty and is not "auto", the module type is determined directly according to the declared value, and the subsequent automatic detection steps are skipped. If the field is missing or the value is "auto", the automatic detection process is entered.

[0029] The module type auto-detection module employs a dual-judgment mechanism: the first judgment is based on the language type declaration field in the module description file, and the second judgment is based on directory content characteristics (file extension distribution). When the two judgments are inconsistent, the first judgment result (declaration field) prevails, and a conflict log is recorded for module developers to troubleshoot. This mechanism balances the explicitness of declarative configuration with the fault tolerance of auto-detection, while also notifying developers through conflict logs to promptly correct any inconsistencies between the declared fields and the actual code.

[0030] refer to Figure 2 The automatic detection process is as follows: Step 201: Traverse the backend code directory of the module and count the distribution of file extensions.

[0031] Step 202: Determine if a .groovy or .kt file exists; if so, proceed to step 203: Mark the module as JVM in-process compilation and load, and distribute it to the first language manager 20.

[0032] Step 204: If it does not exist, further determine if a .jar file exists; if it does, proceed to step 205, mark the module as a JVM classpath isolated loading type, and distribute it to the second language manager 30.

[0033] Step 206: If it does not exist, further determine whether the executable file entry (executable field) is declared in the module description file; if so, proceed to step 207, mark the module as an external process loading type, and distribute it to the third language manager 40.

[0034] Step 208: If none of the above conditions are met, record an error log and skip this module.

[0035] refer to Figure 3 The multi-strategy loading and route registration process is as follows: For JVM in-compile loaded modules (step S2a): The First Language Manager 20 creates a dedicated GroovyClassLoader instance for each module during installation and stores it in the class loader registry. When the module is enabled, it scans the .groovy files in the backend / directory and parses and compiles them into Class objects one by one using GroovyClassLoader. It then parses the route annotations or route declaration methods in the compiled controller class, extracts the HTTP methods, paths, and handler functions, and encapsulates them into route entries for registration with the unified route registry 50. Simultaneously, it registers the compiled Service class in the IoC container.

[0036] For JVM classpath-isolated loaded modules (step S2b): The second language manager 30 scans the .jar files in the backend / directory, creates an independent URLClassLoader instance, and loads the module entry class (which implements the ZephyrPlugin interface). It calls the entry class's routes() method to obtain the list of route declarations and registers them one by one to the unified route registry 50. Simultaneously, it registers the entry class instance to the IoC container.

[0037] For externally loaded modules (step S2c): The third language manager 40 searches for the first unused port number within the system's available port range (e.g., 18000-18999). It starts a child process via the operating system's process creation interface (for C-compiled ELF binaries, it executes directly; for Python, it executes the backend entry script via the Python 3 interpreter), passing the assigned port number to the child process via environment variables or command-line arguments. After the child process starts, the third language manager 40 sends GET requests to http: / / localhost:{port} / health at preset intervals (e.g., every 500 milliseconds), retrying a maximum of 30 times (15 seconds in total). If a 200 response is received, the child process is considered ready; if it times out and is still not ready, a SIGTERM is sent to terminate the child process and a startup failure is reported. Once the child process is ready, it maps the local path pattern " / {moduleKey} / " to a proxy route, forwards HTTP requests to http: / / localhost:{port} / , and registers the proxy route with the unified route registry center 50.

[0038] Child process port allocation, process handle, and health status information are uniformly stored in the process management table for use during the shutdown and uninstallation phases.

[0039] refer to Figure 4 The unified route matching process is as follows: Step 301: Receive the HTTP request and extract the request path and HTTP method.

[0040] Step 302: Search for a route entry that is a complete match (equal path and method) in the route mapping table of the unified route registry 50.

[0041] Step 303: If no exact match is found, traverse the route mapping table to match path parameters and bind the parameter values ​​defined in the path in the form of "{parameter name}" to the corresponding positions in the request path.

[0042] Step 304: If no path parameter match is found, traverse the wildcard routes to perform wildcard path matching and bind the remaining path segments as array-type path parameters.

[0043] Step 305: If any match is found, the request is dispatched to the corresponding route handler; if none are found, a 404 response is returned.

[0044] The routing mapping table of the unified routing registry 50 is stored in groups by module identifier. When a module is deactivated or uninstalled, the corresponding language manager calls the module-based deregistration interface of the unified routing registry 50 to remove all routing entries for that module at once.

[0045] It should be noted that in this embodiment, the unified route registry center runs within the application process (JVM), completing route matching and request distribution through in-process method calls. This is fundamentally different from independently deployed API gateways (such as Nginx and Kong). API gateways perform HTTP forwarding between processes using reverse proxy, while route matching in this solution occurs within the same JVM of the same process, without incurring additional network serialization / deserialization overhead. Furthermore, route entries are organized by source-module-key, supporting application-level module-level operations such as batch unregistration by module, which API gateways cannot provide.

[0046] Example 2: GroovyClassLoader Retention Strategy refer to Figure 5 The specific implementation process of the GroovyClassLoader retention strategy is as follows: Step 401: During module installation, the first language manager 20 creates a GroovyClassLoader instance dedicated to the module and stores it in the global class loader registry (with the module identifier as the key).

[0047] Step 402: When the module is enabled, the Groovy source code file is loaded through the GroovyClassLoader instance, compiled into a Class object and registered as a Bean in the IoC container, and the route is registered at the same time.

[0048] Step 403: When the module is deactivated, all beans loaded by the GroovyClassLoader are deregistered from the IoC container, and all routes of the module are deregistered from the unified route registry 50. However, the GroovyClassLoader instance and its internal compilation cache (scriptCache, classCache) are retained and not destroyed.

[0049] In step 404, when the module is reactivated, the GroovyClassLoader instance retained in step 403 is reused to reload the source code files. Since the same ClassLoader instance is used, the unique identifier of the underlying class metadata of the JVM remains consistent, avoiding the GroovyCastException type conversion exception caused by the JVM treating two classes with the same name as different classes due to the creation of a new ClassLoader.

[0050] Step 405: When a module is unloaded or cleared, the instance is removed from the global class loader registry, its internal compilation cache is cleared, and the close() method is called to release resources.

[0051] In contrast, existing task scheduling frameworks (such as xxl-job) in GLUE mode also use GroovyClassLoader, but create a new ClassLoader instance each time a task is executed and release it immediately after execution. The lifecycle of their GroovyClassLoader is bound to the task execution cycle (typically in milliseconds to seconds), unlike this approach which binds it to the module lifecycle (which can last for days or even longer). This short lifecycle naturally avoids type conflicts across multiple loads, but it also makes it impossible to maintain the continuous running state of Groovy modules and supports persistent lifecycle operations such as enabling / disabling / reinstalling modules. This approach's GCL retention strategy, based on a "space for correctness" design philosophy, sacrifices a small amount of memory to maintain the consistency of class metadata, making it a pioneering solution in this field.

[0052] Example 3: Batch Reflection Cache Cleanup After the compiled and loaded modules within the JVM have finished unloading, the module cache cleanup module 70 performs the following batch cleanup operations: The first group, MyBatis Configuration cache cleanup (obtaining the SqlSessionFactory Configuration object via reflection): (1) mappedStatements: Obtain an instance of type StrictMap through configuration.getMappedStatements(), traverse its internal mappings, and remove entries whose keys contain the module table name prefix; (2) resultMaps: obtained through configuration.getResultMaps(), and similarly filtered and removed by module prefix; (3) caches: retrieved via configuration.getCaches(), and the second-level cache instance associated with the module is removed; (4) parameterMaps: obtained via configuration.getParameterMaps(), removes the parameter mapping associated with the module; (5) sqlFragments and loadedResources: Clean up SQL fragments and loaded resource records imported by the cleanup module; (6) typeAliasRegistry: Obtain the internal TYPE_ALIASES mapping of TypeAliasRegistry through reflection and remove the type aliases registered by the module; (7) typeHandlerRegistry: Obtain TYPE_HANDLER_MAP and REVERSE_TYPE_HANDLER_MAP through reflection, and remove the type handler registered by the module.

[0053] Group 2: MyBatis-Plus global cache cleanup: (8) TABLE_INFO_CACHE: Access the static field TABLE_INFO_CACHE (Map type) of the com.baomidou.mybatisplus.core.toolkit.TableInfoHelper class via reflection to remove the table information entries associated with the module; (9) COLUMN_CACHE_MAP: Access COLUMN_CACHE_MAP of class com.baomidou.mybatisplus.core.metadata.TableFieldInfo via reflection to remove the column cache entries associated with the module; (10) Other global static caches such as tenantCache and autoMappingCache: also clear them one by one through reflection.

[0054] The batch cleanup operation described above is implemented by maintaining a mapping configuration table. Each entry in the table records the cache class name, field name, data type (Map / Set / Collection), and filtering conditions. During cleanup, the configuration table is traversed, field values ​​are obtained through reflection, and module-related entries are removed according to the filtering conditions. This method avoids writing separate cleanup code for each cache structure, achieving a systematic and scalable batch reflection cleanup.

[0055] In practical implementation, the unified module state machine executes a dependency notification process after each successful module state transition: it traverses the module dependency table and queries a list of all target modules that depend on the current module; for each dependent module, it sends a state change event (including the changed module identifier, the state before the change, the state after the change, and the change timestamp) through the notification interface of its corresponding language manager. This mechanism ensures that cross-language inter-module dependencies can be dynamically perceived and responded to at runtime. In particular, after a module is unloaded, the dependent party can promptly unregister the relevant routes and release the held references, avoiding runtime exceptions caused by dangling references.

[0056] Example 4: Port Allocation and Lifecycle Management of External Process Modules The third language manager 40 maintains a process management table that records the module identifier, assigned port number, process ID, startup time, and health status of each external process module.

[0057] The port allocation strategy is to try each port number one by one, starting from the smallest port number, within the preset port range (default 18000-18999).

[0058] For each candidate port, first attempt to create a ServerSocket binding to check if it is already in use; if the binding is successful, immediately release it and select the corresponding port number. If the entire range is occupied during iteration, a startup failure report will be submitted.

[0059] When a module is disabled, the third language manager 40 sends a SIGTERM signal to the child process, waits for a maximum of 5 seconds, and then sends a SIGKILL signal to force termination if the timeout occurs.

[0060] After the child process terminates, the proxy route is deregistered from the unified routing registry (port 50), the port number is released, the record is removed from the process management table, and temporary files (log files, compilation cache, etc.) in the child process's working directory are cleaned up.

[0061] When a module is uninstalled, in addition to executing the deactivation process, the backend source code and module description files are backed up to the backup directory.

[0062] Example 5: Module Conflict Detection and Integrity Protection. The module conflict detection mechanism executes the following steps during the module installation phase: Step 501: Scan the module's backend code directory and resource directory, read all file contents in a preset order, and calculate the SHA-256 hash value of the merged content as the module content fingerprint. Step 502: Query the system module registry (module_registry) to check if a module with the same name already exists; if so, compare the stored SHA-256 fingerprint with the fingerprint calculated in step 501; if the fingerprints are different, it indicates that the module content has been changed (i.e., different versions with the same name), the module status is marked as CONFLICT, installation is prevented, and conflict details are recorded in the conflict log table. This mechanism effectively prevents accidental overwriting of modules with the same name but different versions developed by different teams.

[0063] In summary, the multi-language module unified scheduling method and apparatus provided in this application, through a systematic architecture of automatic module type detection, policy distribution of three language managers, unified route registry, and unified module state machine, achieves unified management of modules in multiple languages ​​such as Groovy, Java, Kotlin, C, and Python within the same scheduling framework. The GroovyClassLoader retention policy specifically addresses the type conflict anomaly caused by repeated creation of ClassLoader during Groovy hot reloading, and the batch reflection cache cleanup mechanism solves the problem of completely clearing the MyBatis cache after module uninstallation. The above technical solutions together constitute a non-obvious systematic solution. It is important to emphasize that there is deep technical coupling between the components of this solution: the state transition of the unified module state machine triggers the route deregistration / registration operation of the unified route registry; the triggering timing of the module cache cleanup module is driven by the UNINSTALL state transition event of the unified module state machine; the GroovyClassLoader retention policy and the route lifecycle management of the unified route registry form a closed loop—the GCL corresponding to route deregistration is retained for reuse during reinstallation. The above coupling relationship shows that this solution is not a simple superposition of independent technologies, but constitutes an inseparable holistic technical solution. Without any core component (such as retaining GCL or a unified routing registry), the entire multilingual unified scheduling framework cannot function properly.

[0064] The embodiments described above are merely illustrative of several implementation methods of this application, and while the descriptions are specific and detailed, they should not be construed as limiting the scope of this patent application. For those skilled in the art, various modifications and improvements can be made without departing from the concept of this application, and these all fall within the protection scope of this application. The protection scope of this patent application shall be determined by the appended claims.

Claims

1. A unified scheduling device for multilingual modular application systems, characterized in that, include: The module type auto-detection module scans the module directory, parses the description files of each module, and automatically determines the language type of the module through a dual determination mechanism that combines the declaration fields of the description file with the characteristics of the directory content. When the module is determined to be a JVM in-process loaded module, it is distributed to the first language manager; when it is determined to be a JVM classpath isolated loaded module, it is distributed to the second language manager; when it is determined to be an external process loaded module, it is distributed to the third language manager. The first language manager is used to dynamically compile JVM-compiled and loaded modules using GroovyClassLoader and register the compiled routes to the unified route registry center. When a module is deactivated, the first language manager retains the corresponding GroovyClassLoader instance without releasing it to eliminate type conflict exceptions caused by the JVM using the fully qualified class name and class loader instance tuple as the unique identifier of the class when the module is reinstalled, resulting in inconsistent class metadata caused by the new instance. The GroovyClassLoader is only turned off when the module is unloaded or cleared. The second language manager is used to load JAR packages and instantiate entry classes for JVM classpath isolated loading modules through URLClassLoader, and register the routes declared by the module to the unified route registry center; The third language manager is used to start independent operating system subprocesses for external process loading modules and allocate dynamic port numbers. After confirming that the subprocess is ready through an HTTP health check probe, the HTTP endpoint of the subprocess is registered as a proxy route to the unified route registration center. The unified route registry center communicates with the first, second, and third language managers and runs inside the application process. It is used to receive route registration requests and uniformly maintain the route mapping table of all language type modules. It supports batch deregistration of routes by module identifier and provides precise path matching, named path parameter matching, and wildcard path matching. This allows the caller to obtain the route processor through in-process method calls without needing to know the implementation language of the called module. A unified module state machine communicates with the first, second, and third language managers to provide the same set of lifecycle state definitions and state transition rules for modules of all language types. Each language manager submits a state transition request through a unified interface. The unified module state machine verifies the validity of the request and executes the transition, while triggering route deregistration or registration operations.

2. The apparatus according to claim 1, characterized in that, The automatic module type detection module employs a dual-determination mechanism as follows: First, it reads the language type declaration field from the module description file. Second, when the language type declaration field is missing or invalid, it scans the file extension distribution in the module's backend directory. The determination logic includes: if a .groovy or .kt file exists, it is determined to be a JVM in-process compiled type; otherwise, if a .jar file exists, it is determined to be a JVM classpath isolated type; otherwise, if an executable file entry declaration exists, it is determined to be an external process loaded type. When the two determinations are inconsistent, the language type declaration field takes precedence, and a conflict log is recorded.

3. The apparatus according to claim 1, characterized in that, The unified route registration center is further configured to: store route mapping tables in groups according to module unique identifiers; when a module is deactivated or uninstalled, receive a request from the corresponding language manager and deregister all route entries for that module at once; when a route conflict occurs, the later registered route with the same path overwrites the previous route, and a conflict log is recorded.

4. The apparatus according to claim 1, characterized in that, It also includes a module cache cleanup module, which is used to clear cache residues generated by the MyBatis persistence layer framework during module runtime in batches through reflection after the loaded modules are compiled and unloaded within the JVM. The module cache cleanup module maintains a static mapping table, which records the class name, field name, data type, and filtering conditions of the cache to be cleaned. The cleanup operation traverses the mapping table, obtains the field values ​​through reflection, and removes the relevant entries of the module according to the filtering conditions, overriding: mapping statement cache, result mapping cache, cache instance, and parameter mapping cache in MyBatis Configuration; and type processor mapping in TypeHandlerRegistry. And MyBatis-Plus's global table information caching and column cache mapping.

5. The apparatus according to claim 1, characterized in that, The third language manager is further configured to: attempt to create a ServerSocket starting from the smallest port within a preset port range to detect occupancy; if the binding is successful, immediately release the port and select the port; after the child process starts, poll the HTTP health check endpoint at preset intervals; if it is not ready within a timeout, determine that the startup has failed and terminate the child process; when the module is stopped or uninstalled, send SIGTERM and SIGKILL signals to the child process in sequence, release the port, and clean up temporary files.

6. The apparatus according to claim 1, characterized in that, The unified module state machine is also used to execute the dependency notification process after the state transition is successful: traverse the module dependency table, query all target modules that depend on the current module; and send a state change event containing the changed module identifier, the state before and after the change, and a timestamp through the notification interface of the language manager corresponding to each dependent module.

7. The apparatus according to claim 1, characterized in that, It also includes a module conflict detection module, which performs the following operations during the module installation phase: scans the module backend code directory and resource directory, reads all file contents in a preset order and calculates the SHA-256 hash value as the module content fingerprint; If a module with the same name already exists and its stored fingerprint is different from the currently calculated fingerprint, the system module registry is queried. If such a module exists and its stored fingerprint is different from the currently calculated fingerprint, the system module will either prevent the installation or log a warning based on the conflict resolution policy declared in the module description file.

8. The apparatus according to claim 1, characterized in that, It also includes a database table structure incremental migration module, which manages changes to the database table structure of each module; each module contains an incremental SQL script directory named with a version number; when a module is installed or upgraded, the system executes all incremental scripts with a version number higher than the current version number of the module in sequence. If the script execution fails, the changes to the current script will be automatically rolled back and the module status will be marked as error.

9. A unified scheduling method for multilingual modular application systems, characterized in that, include: Step S1, Automatic Module Type Detection: Scan the module directory, parse the description files of each module, and automatically determine the language type of the module through a dual judgment mechanism combining the declaration fields of the description files and the characteristics of the directory content; when Groovy or Kotlin source code files exist in the module directory, it is determined to be a JVM in-process loaded module; when JAR archive files exist, it is determined to be a JVM classpath isolated loaded module; when executable file entry declarations exist, it is determined to be an external process loaded module; based on the judgment results, the module is distributed to the corresponding language manager. Step S2, Multi-Strategy Loading and Route Registration: For JVM in-process loaded modules, use GroovyClassLoader to dynamically compile the source code, register the compiled routes to the unified route registry center, and retain the GroovyClassLoader instance when the module is stopped, only closing it when unloaded or cleaned up; for JVM classpath isolated loaded modules, use URLClassLoader... The oader loads the JAR package and instantiates the entry class, registering the routes declared by the module to the unified route registry center. For external process-loaded modules, it starts an independent operating system subprocess and assigns a dynamic port number. After confirming readiness through an HTTP health check probe, it registers the subprocess's HTTP endpoint as a proxy route to the unified route registry center. Step S3, Unified Route Matching: The runtime receives HTTP requests and searches for routes in sequence according to the priority of exact matching, named path parameter matching, and wildcard path matching through the unified route registry center running inside the application process. The requests are then distributed to the corresponding route handlers through in-process method calls. Step S4, Unified State Management: All language-type modules submit state transition requests to the unified module state machine through a unified interface. The unified module state machine performs a validity check based on the current state and the target operation. After the check passes, it executes the state transition, triggers the corresponding route deregistration or registration operation, and notifies all dependent modules.

10. The method according to claim 9, characterized in that, The processing of JVM-compiled and loaded modules in step S2 further includes: during the module installation phase, creating a dedicated GroovyClassLoader instance for the module and storing it in the class loader registry; during the module activation phase, loading and compiling Groovy source code into Class objects using this instance; during the module deactivation phase, deregistering all related Beans and routes from the runtime container and route registry, but retaining the GroovyClassLoader instance without destroying it, using its internal compilation cache to maintain the consistency of JVM class metadata; during the module reactivation phase, reloading the source code using the retained GroovyClassLoader instance, fundamentally avoiding GroovyCastException type conflicts caused by different class loaders despite having the same fully qualified class name due to the creation of a new ClassLoader; and during the module unloading or cleanup phase, removing the instance from the registry and calling its close method to release resources.