Context-Oriented Programming in Java using reflection, dynamic proxies, and bytecode instrumentation. Includes a custom profiler agent for performance analysis.
About • Features • Steps • Usage • Profiler
JavaCOP demonstrates how to implement Context-Oriented Programming (COP) in Java through a progressive, step-by-step approach. The project simulates a phone application that adapts its behavior based on context (INSIDE, OUTSIDE, MEETING), comparing traditional OOP with COP implementations.
Context + Behavior = Dynamic Adaptation
Instead of hardcoded switch statements, COP uses dynamic proxies and feature composition to adapt behavior at runtime based on the active context.
- Dynamic Proxies — Runtime interface implementations via
java.lang.reflect.Proxy - Method Interception — Capturing and routing calls based on context
- Bytecode Instrumentation — Runtime code injection with Javassist
- Java Agent — Non-invasive profiling via Instrumentation API
- Feature Classes — Modular behavior units (Ring, Mute, Vibrate, etc.)
- Context Mapping — Dynamic feature activation based on context
- Proceed Mechanism — Feature chaining similar to aspect-oriented programming
- Method Caching — Performance optimization for reflection-based dispatch
| Step | Description | Technique |
|---|---|---|
| Step 1 | OOP baseline with switch statements |
Traditional Java |
| Step 2 | COP via dynamic proxies | java.lang.reflect.Proxy |
| Step 3 | Feature chaining with proceed() |
Method delegation chain |
| Step 4 | Bytecode profiler agent | Javassist instrumentation |
Classic implementation using conditional statements:
public String getBackgroundColor() {
switch (Mapping.currentContext) {
case OUTSIDE: return "White";
case INSIDE:
case MEETING: return "Black";
}
}Dynamic dispatch through feature classes:
IPhone phone = COP.newCOPInstance(IPhone.class, new PhoneCOP());
// Behavior determined by active features, not switch statementsFeature chaining for cascading behaviors:
public void ring() {
System.out.println("🔔 Ring!");
proceed(); // Calls next feature in chain
}Bytecode instrumentation for performance metrics:
// Automatically injected around methods:
long start = System.nanoTime();
// ... original method ...
long duration = System.nanoTime() - start;- Java JDK 11+
- Javassist (included in
step4/lib/) - Python 3.x (for analysis scripts)
# Run Step 1 (OOP)
make run-step1
# Run Step 2 (COP Proxies)
make run-step2
# Run Step 3 (Proceed)
make run-step3
# Run all with profiler
make profile-all# Compile and run a step
javac step1/Main.java step1/reflection/**/*.java
java step1.Main
# With profiler
make build-profiler
java -javaagent:profiler.jar=results.txt step1.MainToggle caching and logging in Main.java:
COP.setUseCache(true); // Enable method caching
COP.setVerboseLogging(true); // Enable debug outputThe profiler uses Javassist to inject timing and memory measurement code around every method call:
step1.reflection.phone.Phone.ring(): 0.023ms (Memory: 128kb)
step2.reflection.phone.COP.invoke(): 0.156ms (Memory: 256kb)
# Build profiler agent
make build-profiler
# Profile all steps
make profile-all
# Results saved to results_profiler/Python scripts in step4/script_python/ generate performance visualizations:
cd step4/script_python
pip install -r requirements.txt
python plot.py
# Charts saved to Figures/JavaCOP/
├── step1/ # OOP baseline implementation
│ ├── Main.java
│ └── reflection/
│ ├── context/Mapping.java
│ └── phone/
├── step2/ # COP with dynamic proxies
│ ├── Main.java
│ └── reflection/
│ ├── phone/COP.java # Proxy factory
│ └── phone/features/ # Feature classes
├── step3/ # Proceed mechanism
│ ├── Main.java
│ └── reflection/
│ └── phone/Feature.java # Base feature with proceed()
├── step4/ # Profiler agent
│ ├── ProfilerAgent.java # Bytecode instrumentation
│ ├── lib/javassist-3.29.0-GA.jar
│ ├── manifest.txt
│ ├── script_python/ # Analysis scripts
│ │ ├── plot.py
│ │ └── Figures/
│ └── README.md # Detailed analysis results
├── results_profiler/ # Profiler output files
├── guideline.pdf # Project specification
├── Makefile # Build automation
├── .gitignore
└── README.md
This project is developed for academic purposes as part of university coursework.
Built for LINFO2335 - Programming Paradigms @ UCLouvain (Université catholique de Louvain).
Context is king — let your code adapt