or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching.mdindex.mdjava-agent.mdmulti-classloader.mdprogrammatic-weaving.md

multi-classloader.mddocs/

0

# Multi-Classloader Support

1

2

The AspectJ weaver provides comprehensive support for complex classloader hierarchies, OSGi environments, and multi-module applications. The weaving context system allows customization of class loading behavior and resource resolution for different deployment scenarios.

3

4

## Core Context Interfaces

5

6

### IWeavingContext

7

8

Interface for supporting AspectJ in OSGi and multi-classloader environments.

9

10

```java { .api }

11

public interface IWeavingContext {

12

Enumeration<URL> getResources(String name) throws IOException;

13

String getBundleIdFromURL(URL url);

14

String getClassLoaderName();

15

ClassLoader getClassLoader();

16

String getFile(URL url);

17

String getId();

18

boolean isLocallyDefined(String classname);

19

List<Definition> getDefinitions(ClassLoader loader, WeavingAdaptor adaptor);

20

}

21

```

22

23

#### getResources

24

25

Retrieves resources with the given name from the context.

26

27

```java { .api }

28

Enumeration<URL> getResources(String name) throws IOException

29

```

30

31

**Parameters:**

32

- `name` - Resource name to search for

33

34

**Returns:** Enumeration of URLs for matching resources

35

36

**Throws:** `IOException` if resource lookup fails

37

38

#### getBundleIdFromURL

39

40

Returns the bundle ID for a given URL (deprecated, OSGi-specific).

41

42

```java { .api }

43

String getBundleIdFromURL(URL url)

44

```

45

46

**Parameters:**

47

- `url` - URL to get bundle ID for

48

49

**Returns:** Bundle identifier string

50

51

**Deprecated:** This method is deprecated in favor of more generic approaches

52

53

#### getClassLoaderName

54

55

Returns a descriptive name for the classloader.

56

57

```java { .api }

58

String getClassLoaderName()

59

```

60

61

**Returns:** Human-readable name for the classloader

62

63

#### getClassLoader

64

65

Returns the classloader associated with this context.

66

67

```java { .api }

68

ClassLoader getClassLoader()

69

```

70

71

**Returns:** ClassLoader instance for this context

72

73

#### getFile

74

75

Returns the file path for a given URL.

76

77

```java { .api }

78

String getFile(URL url)

79

```

80

81

**Parameters:**

82

- `url` - URL to convert to file path

83

84

**Returns:** File path string

85

86

#### getId

87

88

Returns a unique identifier for this weaving context.

89

90

```java { .api }

91

String getId()

92

```

93

94

**Returns:** Unique context identifier

95

96

#### isLocallyDefined

97

98

Checks if a class is locally defined in this context.

99

100

```java { .api }

101

boolean isLocallyDefined(String classname)

102

```

103

104

**Parameters:**

105

- `classname` - Fully qualified class name

106

107

**Returns:** True if class is defined locally in this context

108

109

#### getDefinitions

110

111

Returns weaving definitions for the given classloader and adaptor.

112

113

```java { .api }

114

List<Definition> getDefinitions(ClassLoader loader, WeavingAdaptor adaptor)

115

```

116

117

**Parameters:**

118

- `loader` - ClassLoader to get definitions for

119

- `adaptor` - WeavingAdaptor instance

120

121

**Returns:** List of Definition objects containing weaving configuration

122

123

### DefaultWeavingContext

124

125

Default implementation of IWeavingContext.

126

127

```java { .api }

128

public class DefaultWeavingContext implements IWeavingContext {

129

public DefaultWeavingContext(ClassLoader loader);

130

// Implements all IWeavingContext methods

131

}

132

```

133

134

#### Constructor

135

136

```java { .api }

137

public DefaultWeavingContext(ClassLoader loader)

138

```

139

140

Creates a default weaving context for the specified classloader.

141

142

**Parameters:**

143

- `loader` - ClassLoader to create context for

144

145

## Specialized ClassLoaders

146

147

### WeavingURLClassLoader

148

149

URLClassLoader implementation with integrated weaving capabilities.

150

151

```java { .api }

152

public class WeavingURLClassLoader extends URLClassLoader implements WeavingClassLoader {

153

public WeavingURLClassLoader(URL[] urls, ClassLoader parent);

154

public WeavingURLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory);

155

// Additional weaving-specific methods

156

}

157

```

158

159

#### Constructors

160

161

```java { .api }

162

public WeavingURLClassLoader(URL[] urls, ClassLoader parent)

163

```

164

165

Creates a weaving classloader with the specified URLs and parent.

166

167

**Parameters:**

168

- `urls` - Array of URLs to load classes from

169

- `parent` - Parent classloader

170

171

```java { .api }

172

public WeavingURLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)

173

```

174

175

Creates a weaving classloader with URLs, parent, and URL stream handler factory.

176

177

**Parameters:**

178

- `urls` - Array of URLs to load classes from

179

- `parent` - Parent classloader

180

- `factory` - URLStreamHandlerFactory for custom protocol handling

181

182

## Configuration and Options

183

184

### Options

185

186

Configuration options for load-time weaving.

187

188

```java { .api }

189

public class Options {

190

// Configuration methods and constants for weaving options

191

}

192

```

193

194

### DefaultMessageHandler

195

196

Default message handler for weaving operations.

197

198

```java { .api }

199

public class DefaultMessageHandler implements IMessageHandler {

200

public DefaultMessageHandler();

201

// Message handling implementation

202

}

203

```

204

205

#### Constructor

206

207

```java { .api }

208

public DefaultMessageHandler()

209

```

210

211

Creates a default message handler for weaving messages.

212

213

## Usage Examples

214

215

### Custom Weaving Context

216

217

```java

218

import org.aspectj.weaver.loadtime.IWeavingContext;

219

import org.aspectj.weaver.loadtime.Aj;

220

221

public class CustomWeavingContext implements IWeavingContext {

222

private final ClassLoader classLoader;

223

private final String contextId;

224

225

public CustomWeavingContext(ClassLoader loader, String id) {

226

this.classLoader = loader;

227

this.contextId = id;

228

}

229

230

@Override

231

public Enumeration<URL> getResources(String name) throws IOException {

232

// Custom resource resolution logic

233

return classLoader.getResources(name);

234

}

235

236

@Override

237

public String getClassLoaderName() {

238

return classLoader.getClass().getSimpleName() + "@" + System.identityHashCode(classLoader);

239

}

240

241

@Override

242

public ClassLoader getClassLoader() {

243

return classLoader;

244

}

245

246

@Override

247

public String getId() {

248

return contextId;

249

}

250

251

@Override

252

public boolean isLocallyDefined(String classname) {

253

// Check if class is defined in this specific classloader

254

try {

255

Class<?> clazz = classLoader.loadClass(classname);

256

return clazz.getClassLoader() == classLoader;

257

} catch (ClassNotFoundException e) {

258

return false;

259

}

260

}

261

262

@Override

263

public List<Definition> getDefinitions(ClassLoader loader, WeavingAdaptor adaptor) {

264

// Return weaving definitions for this context

265

return Collections.emptyList();

266

}

267

268

@Override

269

public String getFile(URL url) {

270

return url.getFile();

271

}

272

273

@Override

274

public String getBundleIdFromURL(URL url) {

275

// Legacy method, return null for non-OSGi environments

276

return null;

277

}

278

}

279

280

// Usage

281

public class CustomWeavingExample {

282

public static void setupCustomWeaving() {

283

ClassLoader loader = Thread.currentThread().getContextClassLoader();

284

IWeavingContext context = new CustomWeavingContext(loader, "custom-context");

285

286

// Create Aj processor with custom context

287

Aj processor = new Aj(context);

288

processor.initialize();

289

290

// Use processor for weaving

291

byte[] originalBytes = getClassBytes("com.example.MyClass");

292

byte[] wovenBytes = processor.preProcess("com.example.MyClass",

293

originalBytes, loader, null);

294

}

295

296

private static byte[] getClassBytes(String className) {

297

// Implementation to get class bytes

298

return new byte[0];

299

}

300

}

301

```

302

303

### Multi-ClassLoader Environment

304

305

```java

306

import org.aspectj.weaver.tools.WeavingAdaptor;

307

import org.aspectj.weaver.loadtime.WeavingURLClassLoader;

308

309

public class MultiClassLoaderExample {

310

public static void setupMultiClassLoaderWeaving() {

311

// Create parent classloader

312

ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();

313

314

// Create weaving classloaders for different modules

315

URL[] moduleAUrls = {getModuleAUrl()};

316

URL[] moduleBUrls = {getModuleBUrl()};

317

318

WeavingURLClassLoader moduleALoader = new WeavingURLClassLoader(moduleAUrls, parentLoader);

319

WeavingURLClassLoader moduleBLoader = new WeavingURLClassLoader(moduleBUrls, parentLoader);

320

321

// Create separate weaving adaptors for each module

322

WeavingAdaptor adaptorA = new WeavingAdaptor(moduleALoader);

323

WeavingAdaptor adaptorB = new WeavingAdaptor(moduleBLoader);

324

325

// Load and weave classes from different modules

326

loadAndWeaveClass(adaptorA, moduleALoader, "com.modulea.ClassA");

327

loadAndWeaveClass(adaptorB, moduleBLoader, "com.moduleb.ClassB");

328

}

329

330

private static void loadAndWeaveClass(WeavingAdaptor adaptor, ClassLoader loader, String className) {

331

try {

332

// Load original class bytes

333

byte[] originalBytes = getClassBytesFromLoader(loader, className);

334

335

// Weave the class

336

byte[] wovenBytes = adaptor.weaveClass(className, originalBytes);

337

338

// Define the class in the appropriate classloader

339

Class<?> wovenClass = defineClass(loader, className, wovenBytes);

340

341

System.out.println("Successfully wove class: " + wovenClass.getName());

342

343

} catch (Exception e) {

344

System.err.println("Failed to weave class " + className + ": " + e.getMessage());

345

}

346

}

347

348

private static URL getModuleAUrl() {

349

// Return URL for module A classes

350

return null;

351

}

352

353

private static URL getModuleBUrl() {

354

// Return URL for module B classes

355

return null;

356

}

357

358

private static byte[] getClassBytesFromLoader(ClassLoader loader, String className) {

359

// Implementation to get class bytes from specific loader

360

return new byte[0];

361

}

362

363

private static Class<?> defineClass(ClassLoader loader, String name, byte[] bytes) {

364

// Implementation to define class in loader

365

return null;

366

}

367

}

368

```

369

370

### OSGi Environment Support

371

372

```java

373

import org.aspectj.weaver.loadtime.IWeavingContext;

374

import org.osgi.framework.Bundle;

375

import org.osgi.framework.BundleContext;

376

377

public class OSGiWeavingContext implements IWeavingContext {

378

private final Bundle bundle;

379

private final BundleContext bundleContext;

380

381

public OSGiWeavingContext(Bundle bundle) {

382

this.bundle = bundle;

383

this.bundleContext = bundle.getBundleContext();

384

}

385

386

@Override

387

public Enumeration<URL> getResources(String name) throws IOException {

388

// Use OSGi bundle resource lookup

389

return bundle.getResources(name);

390

}

391

392

@Override

393

public String getBundleIdFromURL(URL url) {

394

// Extract bundle ID from OSGi URL

395

String path = url.getPath();

396

if (path.startsWith("/bundle")) {

397

String[] parts = path.split("/");

398

if (parts.length > 1) {

399

return parts[1];

400

}

401

}

402

return String.valueOf(bundle.getBundleId());

403

}

404

405

@Override

406

public String getClassLoaderName() {

407

return "OSGi Bundle: " + bundle.getSymbolicName();

408

}

409

410

@Override

411

public ClassLoader getClassLoader() {

412

// OSGi bundles don't expose classloaders directly

413

return this.getClass().getClassLoader();

414

}

415

416

@Override

417

public String getId() {

418

return bundle.getSymbolicName() + "_" + bundle.getVersion();

419

}

420

421

@Override

422

public boolean isLocallyDefined(String classname) {

423

try {

424

// Check if class is provided by this bundle

425

return bundle.loadClass(classname) != null;

426

} catch (ClassNotFoundException e) {

427

return false;

428

}

429

}

430

431

@Override

432

public List<Definition> getDefinitions(ClassLoader loader, WeavingAdaptor adaptor) {

433

// Load weaving definitions from bundle resources

434

List<Definition> definitions = new ArrayList<>();

435

436

try {

437

Enumeration<URL> aopXmlUrls = getResources("META-INF/aop.xml");

438

while (aopXmlUrls.hasMoreElements()) {

439

URL aopXmlUrl = aopXmlUrls.nextElement();

440

// Parse aop.xml and create Definition objects

441

Definition def = parseAopXml(aopXmlUrl);

442

definitions.add(def);

443

}

444

} catch (IOException e) {

445

System.err.println("Failed to load aop.xml from bundle: " + e.getMessage());

446

}

447

448

return definitions;

449

}

450

451

@Override

452

public String getFile(URL url) {

453

return url.getFile();

454

}

455

456

private Definition parseAopXml(URL aopXmlUrl) {

457

// Implementation to parse aop.xml file

458

return null;

459

}

460

}

461

462

// Usage in OSGi environment

463

public class OSGiWeavingExample {

464

public void setupOSGiWeaving(Bundle bundle) {

465

IWeavingContext context = new OSGiWeavingContext(bundle);

466

Aj processor = new Aj(context);

467

processor.initialize();

468

469

// Use processor for OSGi-aware weaving

470

}

471

}

472

```

473

474

### Class Loading Isolation

475

476

```java

477

import org.aspectj.weaver.tools.cache.WeavedClassCache;

478

479

public class IsolatedWeavingExample {

480

public static void setupIsolatedWeaving() {

481

// Create isolated classloaders for different application modules

482

ClassLoader appLoader = createApplicationClassLoader();

483

ClassLoader pluginLoader1 = createPluginClassLoader("plugin1");

484

ClassLoader pluginLoader2 = createPluginClassLoader("plugin2");

485

486

// Create separate caches for each classloader

487

List<String> appAspects = Arrays.asList("com.app.LoggingAspect");

488

List<String> plugin1Aspects = Arrays.asList("com.plugin1.SecurityAspect");

489

List<String> plugin2Aspects = Arrays.asList("com.plugin2.MetricsAspect");

490

491

WeavedClassCache appCache = WeavedClassCache.createCache(appLoader, appAspects, null, null);

492

WeavedClassCache plugin1Cache = WeavedClassCache.createCache(pluginLoader1, plugin1Aspects, null, null);

493

WeavedClassCache plugin2Cache = WeavedClassCache.createCache(pluginLoader2, plugin2Aspects, null, null);

494

495

// Each cache operates independently with its own classloader scope

496

System.out.println("App cache: " + appCache.getName());

497

System.out.println("Plugin1 cache: " + plugin1Cache.getName());

498

System.out.println("Plugin2 cache: " + plugin2Cache.getName());

499

}

500

501

private static ClassLoader createApplicationClassLoader() {

502

URL[] urls = {getApplicationJarUrl()};

503

return new URLClassLoader(urls, ClassLoader.getSystemClassLoader());

504

}

505

506

private static ClassLoader createPluginClassLoader(String pluginName) {

507

URL[] urls = {getPluginJarUrl(pluginName)};

508

return new URLClassLoader(urls, ClassLoader.getSystemClassLoader());

509

}

510

511

private static URL getApplicationJarUrl() {

512

// Return URL for application JAR

513

return null;

514

}

515

516

private static URL getPluginJarUrl(String pluginName) {

517

// Return URL for plugin JAR

518

return null;

519

}

520

}

521

```

522

523

## Configuration

524

525

### Context-Specific Configuration

526

527

Different classloader contexts can have different weaving configurations:

528

529

```xml

530

<!-- META-INF/aop.xml for Module A -->

531

<aspectj>

532

<weaver options="-verbose">

533

<include within="com.modulea..*"/>

534

</weaver>

535

<aspects>

536

<aspect name="com.modulea.LoggingAspect"/>

537

</aspects>

538

</aspectj>

539

```

540

541

```xml

542

<!-- META-INF/aop.xml for Module B -->

543

<aspectj>

544

<weaver options="-showWeaveInfo">

545

<include within="com.moduleb..*"/>

546

</weaver>

547

<aspects>

548

<aspect name="com.moduleb.SecurityAspect"/>

549

</aspects>

550

</aspectj>

551

```

552

553

### System Properties

554

555

- **`aj.class.path`**: Additional classpath for aspect resolution

556

- **`org.aspectj.weaver.loadtime.configuration`**: Custom configuration file location

557

- **`aj.weaving.loadtime.configuration.debug`**: Debug configuration loading

558

559

## Best Practices

560

561

1. **Context Isolation**: Use separate weaving contexts for different modules

562

2. **Resource Management**: Properly clean up classloaders and contexts

563

3. **Cache Scoping**: Use appropriate cache scoping for classloader hierarchies

564

4. **Configuration Management**: Keep weaving configuration close to the code it affects

565

566

## Troubleshooting

567

568

### Common Issues

569

570

1. **ClassNotFoundException**: Check classloader hierarchy and resource visibility

571

2. **Aspect Not Applied**: Verify aspect is visible from the target class's classloader

572

3. **Memory Leaks**: Ensure proper cleanup of custom classloaders and contexts

573

574

### Debug Output

575

576

```java

577

// Enable classloader debugging

578

System.setProperty("aj.weaving.loadtime.configuration.debug", "true");

579

System.setProperty("java.system.class.loader", "custom.DebuggingClassLoader");

580

```

581

582

### Context Information

583

584

```java

585

public static void printContextInfo(IWeavingContext context) {

586

System.out.println("Context ID: " + context.getId());

587

System.out.println("ClassLoader: " + context.getClassLoaderName());

588

System.out.println("ClassLoader instance: " + context.getClassLoader());

589

590

// Test resource resolution

591

try {

592

Enumeration<URL> resources = context.getResources("META-INF/aop.xml");

593

while (resources.hasMoreElements()) {

594

System.out.println("Found aop.xml: " + resources.nextElement());

595

}

596

} catch (IOException e) {

597

System.err.println("Failed to load resources: " + e.getMessage());

598

}

599

}

600

```