Profile Blocking Skill
Identify blocking calls in the reactive codebase that can cause thread starvation, deadlocks, and performance degradation in Spring WebFlux applications.
Instructions
1. Search for Blocking Patterns
Use Grep to search for these blocking call patterns:
Direct Blocking Calls
java1.block() // Mono/Flux blocking subscription 2.blockFirst() // Flux blocking first element 3.blockLast() // Flux blocking last element 4.blockOptional() // Mono blocking to Optional 5.toFuture().get() // CompletableFuture blocking 6.get() // Future.get() blocking 7.join() // CompletableFuture.join()
Thread Blocking
java1Thread.sleep( // Thread sleep 2Object.wait( // Object monitor wait 3.await( // CountDownLatch, CyclicBarrier await 4.acquire( // Semaphore blocking acquire 5synchronized // Synchronized blocks (potential) 6ReentrantLock.lock // Explicit locking
Blocking I/O
java1InputStream // Blocking input streams 2OutputStream // Blocking output streams 3FileInputStream // File I/O 4FileOutputStream // File I/O 5BufferedReader // Blocking readers 6Scanner // Blocking scanner 7new URL( // URL.openStream() is blocking 8HttpURLConnection // Blocking HTTP
JDBC/Database (if present)
java1JdbcTemplate // Blocking JDBC 2EntityManager // Blocking JPA 3.save( // Repository blocking save 4.findBy // Repository blocking find 5DataSource // Direct datasource access
2. Context-Aware Analysis
For each finding, determine if it's:
Acceptable blocking:
- Inside
StructuredTaskScope(this project uses Java 24 virtual threads) - In
@Scheduledmethods running on separate thread pool - In test code
- Wrapped in
Mono.fromCallable()with.subscribeOn(Schedulers.boundedElastic()) - In startup/initialization code (non-request path)
Problematic blocking:
- In
@RestControllermethods returningMono/Flux - In reactive chain operators (map, flatMap, filter)
- On Netty event loop threads
- In
WebFilterimplementations - Inside
Mono.create()orFlux.create()without scheduler
3. Analyze Reactive Chains
Check for anti-patterns in reactive code:
java1// BAD: Blocking in map 2mono.map(data -> { 3 blockingCall(); // Blocks event loop! 4 return result; 5}) 6 7// BAD: Blocking in flatMap 8flux.flatMap(item -> { 9 var result = blockingService.call(); // Blocks! 10 return Mono.just(result); 11}) 12 13// GOOD: Proper offloading 14mono.flatMap(data -> 15 Mono.fromCallable(() -> blockingCall()) 16 .subscribeOn(Schedulers.boundedElastic()) 17)
4. Check This Project's Specific Patterns
Files to examine:
src/main/java/**/controller/*.java- REST endpointssrc/main/java/**/service/*.java- Service layersrc/main/java/**/strategy/*.java- Strategy implementationssrc/main/java/**/config/*.java- Configuration classes
Known acceptable patterns in this project:
StructuredTaskScopeusage inAggregatorService(virtual threads).block()inside virtual thread contexts- OkHttp calls (executed in separate thread pool)
Patterns to flag:
.block()in controller methods- Blocking in
WebFilterorHandlerFilterFunction - Synchronous HTTP calls without proper scheduling
5. Virtual Thread Considerations
This project uses Java 24 with virtual threads. Check:
java1// Virtual thread factory usage 2Thread.ofVirtual().factory() 3 4// StructuredTaskScope usage (blocking is OK inside) 5try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { 6 scope.fork(() -> blockingCall()); // OK - virtual thread 7 scope.join(); // OK - virtual thread blocks, not platform thread 8}
6. HTTP Client Analysis
Check OkHttp usage patterns:
java1// Synchronous call - check if on reactive thread 2Response response = client.newCall(request).execute(); 3 4// Better: Use async 5client.newCall(request).enqueue(callback); 6 7// Or wrap properly 8Mono.fromCallable(() -> client.newCall(request).execute()) 9 .subscribeOn(Schedulers.boundedElastic())
Output Format
markdown1## Blocking Call Analysis Report 2 3### Summary 4| Category | Count | Severity | 5|----------|-------|----------| 6| Direct .block() calls | X | High/Medium | 7| Thread.sleep() | X | High | 8| Blocking I/O | X | Medium | 9| Synchronized blocks | X | Low | 10| **Total potential issues** | **Y** | | 11 12### Critical Issues (Event Loop Blocking) 13 14#### [Issue Title] 15**File**: `path/to/file.java:line` 16**Pattern**: `.block()` in reactive chain 17**Context**: Inside @RestController endpoint 18**Risk**: Thread starvation, request timeouts 19```java 20// Current code 21@GetMapping("/data") 22public Mono<Data> getData() { 23 return service.fetchData() 24 .map(d -> blockingTransform(d)); // BLOCKS! 25}
Fix:
java1@GetMapping("/data") 2public Mono<Data> getData() { 3 return service.fetchData() 4 .flatMap(d -> Mono.fromCallable(() -> blockingTransform(d)) 5 .subscribeOn(Schedulers.boundedElastic())); 6}
Medium Priority (Potential Issues)
| File | Line | Pattern | Context | Verdict |
|---|---|---|---|---|
| Service.java | 42 | .block() | Inside StructuredTaskScope | OK |
| Handler.java | 78 | Thread.sleep | Test code | OK |
Acceptable Blocking (Verified Safe)
These blocking calls are in appropriate contexts:
| File | Line | Pattern | Why It's OK |
|---|---|---|---|
| AggregatorService.java | 120 | .block() | Inside virtual thread scope |
| ForecastService.java | 85 | OkHttp.execute() | Wrapped in fromCallable |
Patterns Found
.block() Calls
src/main/java/.../Service.java:42 - response.block()
src/main/java/.../Service.java:87 - result.blockFirst()
Thread Blocking
src/main/java/.../Worker.java:23 - Thread.sleep(1000)
Blocking I/O
src/main/java/.../Reader.java:15 - new FileInputStream()
Recommendations
- Immediate: Move blocking call at
File.java:42to bounded elastic scheduler - Review: Verify StructuredTaskScope usage covers all blocking in AggregatorService
- Consider: Replace synchronous OkHttp with async calls or WebClient
Reactive Best Practices Checklist
- No .block() in @RestController methods
- No .block() in WebFilter implementations
- Blocking I/O wrapped with boundedElastic scheduler
- Thread.sleep() only in tests or scheduled tasks
- Synchronized blocks minimized and not in hot paths
- HTTP clients properly configured for async or offloaded
## Execution Steps
1. Use `Grep` to find all `.block()` calls
2. Use `Grep` to find `Thread.sleep`, `.await(`, `synchronized`
3. Use `Grep` to find blocking I/O patterns
4. Read each file to determine context (controller vs service vs test)
5. Check if blocking is inside StructuredTaskScope or virtual thread
6. Categorize findings by severity
7. Generate report with fix recommendations
## Notes
- Virtual threads (Java 21+) change the blocking calculus - blocking is OK on virtual threads
- This project uses StructuredTaskScope, so verify scope boundaries
- OkHttp is blocking by default but may be acceptable if not on event loop
- Focus on request-handling paths; scheduled tasks are lower priority
- Some `.block()` in tests is normal and acceptable
- Spring WebFlux Netty uses limited event loop threads - blocking them is critical