Skip to content

Conversation

Copy link

Copilot AI commented Nov 16, 2025

Analyzed the circular dependency between org.jnode.vm.core and rt plugins at Java source level. Identified 154 classes involved, sorted by dependency count, and proposed concrete refactoring strategies. Implemented Phase 1, reducing the circular dependency from 154 to 153 classes.

Analysis Tool

analyze_vm_core_rt_cycle.py - Automated dependency analyzer that:

  • Maps Java packages to plugins via descriptor exports
  • Analyzes import statements to track cross-plugin dependencies
  • Generates sorted reports by dependency count
python3 analyze_vm_core_rt_cycle.py
# Output: VM_CORE_RT_CYCLE_DETAILED_ANALYSIS.md

Key Findings

153 classes in cycle (reduced from 154):

  • 112 vm.core → rt (was 113, mostly java.util., java.io., java.security.*)
  • 41 rt → vm.core (31 are Native* implementations)

Top refactoring candidates (1 dependency each):

  • vm.core: JNodePermissionMoved to rt, VmSystemSettings, BaseVmArchitecture
  • rt: javax.isolate.Isolate, javax.isolate.Link, javax.isolate.StreamBindings

Implementation Status

Phase 1 - Quick win:COMPLETE - Moved JNodePermission from vm.core to rt

  • Moved core/src/core/org/jnode/permission/JNodePermission.java to core/src/classpath/vm/org/jnode/permission/JNodePermission.java
  • Updated rt plugin descriptor to export org.jnode.permission.*
  • Updated vm.core plugin descriptor to remove org.jnode.permission.* export
  • Result: Reduced circular dependency from 154 to 153 classes

Phase 2 - Isolate API: Extract org.jnode.vm.isolate.api plugin with interfaces only, breaking javax.isolate ↔ VmIsolate cycle (3-5 days)

Phase 3 - Accept design: 31/41 rt→vm.core dependencies are Native* implementations (NativeObject, NativeSystem, etc.). This coupling is fundamental to JNode's bootstrap architecture - document rather than eliminate.

Architecture Insight

The VM and runtime are intentionally coupled through native method implementations. Full cycle elimination is neither necessary nor beneficial. Focus: reduce accidental coupling, document intentional coupling.

Documentation

  • VM_CORE_RT_CYCLE_DETAILED_ANALYSIS.md - Complete 153-class breakdown sorted by dependency count (updated)
  • BREAKING_VM_CORE_RT_CYCLE_PROPOSAL.md - 3-phase implementation plan with risk assessment
  • CIRCULAR_DEPENDENCY_README.md - Usage guide and quick reference
  • CIRCULAR_DEPENDENCY_SUMMARY.md - Executive summary
Original prompt
  • Read documentations in docs/plugins.
  • List detailed (especially which java class has dependency with the other package/plugin in the cycle) source level dependencies between org.jnode.vm.core and rt (it's a circular dependency at source level).
  • Sort the result starting starting by class with less dependencies but involved in circular dependency. Don't include classes not involved in the circular dependency.
  • Propose me somthing to break the circular dependency.

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 5 commits November 16, 2025 13:07
Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
Copilot AI changed the title [WIP] Document source level dependencies in circular dependency Analyze and document org.jnode.vm.core ↔ rt circular dependency at source level Nov 16, 2025
Copilot AI requested a review from fduminy November 16, 2025 13:15
@fduminy
Copy link
Owner

fduminy commented Nov 16, 2025

@copilot apply "Phase 1"

- Moved core/src/core/org/jnode/permission/JNodePermission.java
  to core/src/classpath/vm/org/jnode/permission/JNodePermission.java
- Added org.jnode.permission.* export to rt plugin descriptor
- Removed org.jnode.permission.* export from vm.core plugin descriptor
- Reduced circular dependency from 154 to 153 classes

Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
Copy link
Author

Copilot AI commented Nov 16, 2025

@copilot apply "Phase 1"

Phase 1 complete! ✅

Moved JNodePermission from org.jnode.vm.core to rt plugin as proposed.

Results:

  • Circular dependency reduced from 154 to 153 classes
  • vm.core → rt: 112 classes (was 113)
  • rt → vm.core: 41 classes (unchanged)

Changes in commit 9290402:

  • Moved JNodePermission.java from core/src/core/ to core/src/classpath/vm/
  • Updated rt descriptor to export org.jnode.permission.*
  • Updated vm.core descriptor to remove org.jnode.permission.* export
  • Regenerated analysis report with updated numbers

The analysis tool confirms the change is working correctly. JNodePermission now lives in rt where it belongs (only depends on java.security.BasicPermission).

Copilot AI changed the title Analyze and document org.jnode.vm.core ↔ rt circular dependency at source level Analyze, document, and reduce org.jnode.vm.core ↔ rt circular dependency at source level Nov 16, 2025
@fduminy
Copy link
Owner

fduminy commented Nov 16, 2025

@copilot I still see the circular dependency between org.jnode.vm.core and rt by running analyze_source_cycles.py

Copy link
Author

Copilot AI commented Nov 16, 2025

@copilot I still see the circular dependency between org.jnode.vm.core and rt by running analyze_source_cycles.py

You're correct - the plugin-level circular dependency still exists.

What Phase 1 achieved:

  • Reduced the number of classes involved in the cycle from 154 to 153
  • This is an incremental improvement, but doesn't break the cycle itself

Why the cycle still exists:
To break the plugin-level circular dependency, we need to eliminate all dependencies in one direction. Currently:

  • 112 classes in vm.core still import from rt (java.util., java.io., etc.)
  • 41 classes in rt still import from vm.core (Native* implementations)

The reality:
As noted in the proposal, the vast majority of these dependencies are fundamental to the architecture:

  • vm.core needs standard Java classes (Collections, I/O, etc.) from rt
  • rt's native implementations need VM internals from vm.core

This is a classic bootstrap coupling that cannot be fully eliminated without major architectural changes. Phase 1 was about reducing accidental coupling (JNodePermission). The remaining ~153 classes represent intentional architectural coupling.

The proposal's recommendation is to accept most of this coupling as by-design and focus only on the few accidental dependencies (like JNodePermission) that can be reasonably moved.

Co-authored-by: fduminy <143904+fduminy@users.noreply.github.com>
@fduminy
Copy link
Owner

fduminy commented Nov 16, 2025

@copilot how can I deal with this circular dependencies if i convert each jnode plugin to a maven module ?

Copy link
Author

Copilot AI commented Nov 16, 2025

@copilot how can I deal with this circular dependencies if i convert each jnode plugin to a maven module ?

Maven doesn't allow circular dependencies between modules - the build will fail. Here are your options:

Option 1: Merge Circular Modules (Recommended for vm.core ↔ rt)
Combine vm.core and rt into a single Maven module. This makes sense because:

  • Their coupling is fundamental (bootstrap architecture)
  • 153 classes are interdependent
  • Native implementations inherently need VM access
  • Trying to separate them would be artificial

Option 2: Extract Common API Module
Create a new module (e.g., jnode-vm-api) containing only interfaces:

  • Both vm.core and rt depend on this API module
  • Move shared interfaces there
  • This works for the isolate APIs (Phase 2) but won't help with Native* implementations

Option 3: Use Maven's provided scope
For cases where one module needs types from another at compile time but not runtime:

<dependency>
  <groupId>org.jnode</groupId>
  <artifactId>jnode-vm-core</artifactId>
  <scope>provided</scope>
</dependency>

This won't break Maven's build order but doesn't truly eliminate the cycle.

Practical Recommendation:

  1. Merge vm.core + rt into one Maven module (they're fundamentally coupled)
  2. Apply Phase 2 for isolate APIs (extract to separate module)
  3. Keep other plugins as separate modules

The mavenizer tool in the repository may need updates to handle this merged module approach.

@fduminy
Copy link
Owner

fduminy commented Nov 16, 2025

@copilot If I name TOTO the merge of org.jnode.vm.core and rt,
I still see 3 small cycles :

  • org.jnode.plugin and TOTO
  • org.jnode.runtime.core.resource and TOTO
  • org.jnode.vm and TOTO
    and the dependency org.jnode.vm → org.jnode.runtime.core.resource make a bigger cycle with the last 2 small ones

Copy link
Author

Copilot AI commented Nov 16, 2025

@copilot If I name TOTO the merge of org.jnode.vm.core and rt,
I still see 3 small cycles :

  • org.jnode.plugin and TOTO...

Correct observation! After merging vm.core + rt into TOTO, you'd still have these cycles:

Small cycles with TOTO:

  1. org.jnode.plugin ↔ TOTO

    • plugin needs rt classes
    • vm.core needs plugin classes (for plugin system)
  2. org.jnode.runtime.core.resource ↔ TOTO

    • runtime.core.resource needs rt classes
    • rt needs runtime.core.resource
    • vm.core needs runtime.core.resource
  3. org.jnode.vm ↔ TOTO

    • vm needs vm.core
    • vm.core needs vm

Larger cycle:
org.jnode.vm → org.jnode.runtime.core.resource ↔ TOTO

Maven strategy:
You have two approaches:

A) Merge more aggressively (simplest):

  • Merge: TOTO + org.jnode.plugin + org.jnode.runtime.core.resource + org.jnode.vm
  • Creates one "jnode-core" module with everything tightly coupled
  • Cleanest for Maven but loses modularity

B) Keep some separation (more complex):

  • Keep TOTO as one module
  • Make org.jnode.plugin, org.jnode.runtime.core.resource, org.jnode.vm depend on TOTO with provided scope
  • Accept that these are "fragment" modules that extend TOTO
  • Similar to OSGi fragments pattern

Option A is recommended for Maven conversion - these 5 plugins form the bootstrap core and are fundamentally coupled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants