java-doctor

Comprehensive Java code health analyzer. 0-100 score with diagnostics. Progressive loading - detects project tech (Spring, gRPC, JPA) and loads relevant rules. Version-aware for Java 8-25 & Spring Boot 3.x/4.x. Virtual threads, structured concurrency, and deep testing checks included. Use when reviewing Java code, finding bugs, or preparing for PR.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "java-doctor" with this command: npx skills add ajaywadhara/java-doctor

Java Doctor - Comprehensive Java Code Health Analyzer

You are an expert Java code reviewer. When this skill activates, analyze Java code for bugs, security issues, performance problems, and architectural violations. Output a 0-100 score with actionable diagnostics.

Your Task - Progressive Analysis Workflow

Step 1: Detect Project Technologies (ALWAYS RUN FIRST)

Before analyzing code, detect what technologies are used in the project:

Check these files to detect technologies:

  • pom.xml - Maven dependencies
  • build.gradle or build.gradle.kts - Gradle dependencies
  • build.xml - Ant (legacy)
  • pom.xml - Check for grpc, spring, jakarta keywords
  • build.gradle - Check for plugins and dependencies

Technology Detection Patterns:

TechnologyMaven (pom.xml)GradleDetection Priority
Spring Bootspring-boot-starter-parentid("org.springframework.boot")HIGH
Spring Frameworkspring-context, spring-webspring-context, spring-webHIGH
Jakarta EEjakarta.*jakarta.*HIGH
gRPCgrpc-java, grpc-protobufgrpc-javaHIGH
JPA/Hibernatespring-data-jpa, hibernate-corespring-data-jpaMEDIUM
JUnitjunit-jupiter, junitjunit-jupiterMEDIUM
TestcontainerstestcontainerstestcontainersLOW
LomboklomboklombokLOW
KotlinN/Akotlin("stdlib")LOW

Step 2: Load Relevant Rules Based on Detection

Load rules incrementally:

  1. ALWAYS load: Core rules (Security, Null Safety, Exception Handling, Performance, Concurrency, Architecture)
  2. If Spring Boot detected: Load Spring/Boot 4.x rules
  3. If gRPC detected: Load gRPC rules
  4. If JPA detected: Load JPA/Hibernate rules
  5. If Lombok detected: Load Lombok rules
  6. If Java 21+ detected: Load Virtual Threads & Structured Concurrency rules
  7. Always load: Google Checkstyle rules, Testing Depth rules

Step 3: Ask for Missing Information

If technologies cannot be detected:

Question: "I couldn't detect all technologies in your project. Which technologies are you using?"
Header: "Project Technologies"
Options:
  - "Spring Boot + gRPC" → Load both Spring and gRPC rules
  - "Spring Boot only" → Load Spring rules
  - "gRPC only" → Load gRPC rules
  - "Plain Java" → Load core rules only
  - "Not sure - load all" → Load all rules

Core Rules (Always Load)

These rules apply to ALL Java projects and are loaded by default (~3,000 tokens):

1. Security (16 rules)

2. Null Safety (8 rules)

3. Exception Handling (8 rules)

4. Performance (12 rules)

5. Concurrency (12 rules)

6. Architecture (10 rules)

7. Logging (7 rules)

8. Google Checkstyle (35 rules)

Technology-Specific Rules (Load On-Demand)

9. Spring Framework / Spring Boot (23 rules)

Load if Spring detected: pom.xml contains spring-boot or spring-context

10. gRPC Java (26 rules)

Load if gRPC detected: pom.xml contains grpc-java or grpc-protobuf

11. JPA / Hibernate (15 rules)

Load if JPA detected: pom.xml contains hibernate or spring-data-jpa

12. Lombok (5 rules)

Load if Lombok detected: pom.xml contains lombok

13. Build Tools - Maven/Gradle (20 rules)

Always check: Check pom.xml or build.gradle for best practices

Java Version Detection

Detect Java version by checking:

  • pom.xml - Look for <java.version> or <maven.compiler.source>
  • build.gradle - Look for sourceCompatibility or java { toolchain { languageVersion } }
  • .java-version or SDKMAN config

If version cannot be detected from any of these sources, ASK the user:

Question: "I couldn't detect the Java version from your project. Which Java version is your project using?"
Header: "Java Version"
Options:
  - "Java 8 (1.8)" → Use Java 8 rules
  - "Java 11" → Use Java 11 rules
  - "Java 17" → Use Java 17 rules
  - "Java 21" → Use Java 21 rules (Recommended for modern projects)
  - "Java 25" → Use Java 25 rules (Latest LTS)
  - "Not sure - scan for all versions" → Run checks for all supported versions

Also detect Spring Boot version (if Spring Boot project):

  • pom.xml - Look for <parent><version> with spring-boot-starter-parent
  • build.gradle - Look for springBootVersion or id("org.springframework.boot") version "x.x.x"
Question: "I detected a Spring Boot project but couldn't determine the version. Which Spring Boot version are you using?"
Header: "Spring Boot Version"
Options:
  - "Spring Boot 3.x" → Use Spring Boot 3.x rules (Jakarta EE 9+, Security 6.x)
  - "Spring Boot 4.x" → Use Spring Boot 4.x rules (Jakarta EE 11, Security 7.x)
  - "Not sure" → Run checks for both versions

Version-Specific Checks:

VersionSpecific Checks
Java 8Stream API usage, lambda best practices, try-with-resources, Optional
Java 11Local-Variable Type Inference (var), String improvements, Files.readString()
Java 17Sealed classes, Pattern matching for instanceof, Records basics
Java 21Virtual threads (VT-001 to VT-010), Structured concurrency, Sequenced collections, Record patterns, Pattern matching for switch
Java 25Scoped Values (JEP 506), Primitive Patterns (JEP 507), Flexible Constructor Bodies (JEP 513), Stable Values (JEP 502), Module Import Declarations (JEP 511)

Virtual Threads (Java 21+):

  • Use Thread.ofVirtual().start() or Executors.newVirtualThreadPerTaskExecutor()
  • Replace newFixedThreadPool with virtual thread executors for I/O-bound tasks
  • Do NOT use Thread.sleep() in virtual threads (use LockSupport.parkNanos())

Spring Boot Version Detection

Also detect Spring Boot version by checking:

  • pom.xml - Look for <parent><version> with spring-boot-starter-parent
  • build.gradle - Look for springBootVersion in ext or plugins { id 'org.springframework.boot' }
  • build.gradle - Look for id("org.springframework.boot") version "x.x.x"
  • application.properties/yml - Check spring-boot.version property

If Spring Boot version detected:

VersionSpecific Checks
Spring Boot 3.xJakarta EE 9+, Spring Security 6.x, Jackson 2.x
Spring Boot 4.xJakarta EE 11, Spring Security 7.x, Jackson 3.x, JUnit 6, Observability starter

Score Calculation

Base Score: 100 (Starts perfect, deduct points for issues)

SeverityDeductionExample
CRITICAL-15 eachSecurity vulnerability, NPE risk, resource leak
ERROR-10 eachMissing null check, improper exception handling
WARNING-5 eachCode smell, performance concern, missing @Override
SUGGESTION-2 eachStyle improvement, Effective Java recommendation

Score Ranges:

  • 75-100: Great - Production-ready code
  • 50-74: Needs Work - Address warnings before release
  • 0-49: Critical - Blockers must be fixed

Rule Categories (~280 rules)

Progressive Loading:

  • Core Rules (~100 tokens) - Always loaded
  • Spring/Boot Rules (~500 tokens) - Loaded if Spring detected
  • gRPC Rules (~600 tokens) - Loaded if gRPC detected
  • JPA Rules (~300 tokens) - Loaded if JPA detected
  • Build Rules (~200 tokens) - Always checked

1. Security (CRITICAL - Always Check First)

Rule IDIssueSeverityFix
SEC-001Hardcoded passwords/secrets/keysCRITICALUse environment variables or config
SEC-002SQL injection (string concatenation in queries)CRITICALUse parameterized queries
SEC-003Sensitive data in logs (passwords, tokens, PII)CRITICALMask sensitive fields
SEC-004Missing input validation on public methodsERRORAdd @Valid, Bean Validation
SEC-005Weak cryptographic algorithms (MD5, SHA1)CRITICALUse SHA-256+, AES-256
SEC-006Missing authentication/authorization checksCRITICALAdd security annotations
SEC-007XML External Entity (XXE) vulnerabilityCRITICALDisable external entities
SEC-008Deserialization of untrusted dataCRITICALUse whitelisting, ObjectInputFilter
SEC-009Path traversal vulnerabilityCRITICALValidate and sanitize paths
SEC-010Missing CORS configuration on public APIsWARNINGExplicit CORS policy
SEC-011Weak password hashing (MD5, SHA1 for passwords)CRITICALUse BCrypt, Argon2, PBKDF2
SEC-012Insecure random number generationERRORUse SecureRandom
SEC-013Hardcoded salt for hashingWARNINGUse random salt per user
SEC-014Trust boundary violationWARNINGValidate all cross-boundary data
SEC-015LDAP injectionCRITICALSanitize LDAP input
SEC-016XPath injectionCRITICALUse parameterized XPath

2. Null Safety & Correctness

Rule IDIssueSeverityFix
NULL-001Optional.get() without isPresent checkCRITICALUse orElseThrow(), orElse()
NULL-002Null check on primitive wrapper (autoboxing)ERRORUse Optional, default values
NULL-003Returning null instead of empty collectionWARNINGReturn empty collection
NULL-004Null parameter without validationERRORAdd null checks, @NonNull
NULL-005Chained method calls without null guardsERRORUse Optional chaining
NULL-006Overloading with null parametersWARNINGUse method overloading carefully
NULL-007Null-safety annotation missing (@NonNull, @Nullable)SUGGESTIONAdd null annotations
NULL-008Mutable fields that should be immutableWARNINGMake final, use builder

3. Exception Handling

Rule IDIssueSeverityFix
EXC-001Swallowed exceptions (empty catch block)ERRORLog and rethrow, or handle
EXC-002Catching generic Exception/ThrowableWARNINGCatch specific exceptions
EXC-003Throwing generic RuntimeExceptionWARNINGUse specific exception types
EXC-004Swallowing InterruptedExceptionWARNINGRestore interrupt flag
EXC-005Not using try-with-resourcesERRORUse try-with-resources
EXC-006Finally block returning or throwingCRITICALMove outside finally
EXC-007Exception catching order (subclass after super)WARNINGCatch subclass first
EXC-008Suppressed exceptions not handledWARNINGHandle via getSuppressed()

4. Performance

Rule IDIssueSeverityFix
PERF-001N+1 query problemCRITICALUse JOIN FETCH, EntityGraph
PERF-002EAGER fetching on collectionsERRORUse LAZY, fetch explicitly
PERF-003String concatenation in loopsERRORUse StringBuilder
PERF-004Boxing/Unboxing in loopsWARNINGUse primitive streams
PERF-005Creating unnecessary objectsWARNINGReuse, use flyweight
PERF-006Missing database indexes (in comments)WARNINGAdd index hints
PERF-007Large blob/clob in entityWARNINGUse LAZY, separate table
PERF-008Unclosed streams, connections, filesCRITICALUse try-with-resources
PERF-009Synchronized on mutable objectsERRORUse immutable objects
PERF-010HashMap in concurrent environmentERRORUse ConcurrentHashMap
PERF-011Inefficient collection: LinkedList for random accessWARNINGUse ArrayList
PERF-012toArray() without generic typeWARNINGUse toArray(new Type[0])

5. Concurrency & Thread Safety

Rule IDIssueSeverityFix
CONC-001Shared mutable state between threadsCRITICALUse immutability, synchronization
CONC-002Double-checked locking broken (pre-Java 5)CRITICALUse volatile or eager init
CONC-003Starting thread in constructorCRITICALUse lazy initialization
CONC-004Calling overridable methods from constructorERRORUse initializer blocks
CONC-005Missing volatile on shared variablesERRORAdd volatile keyword
CONC-006Using Thread.stop()CRITICALUse interruption pattern
CONC-007Not handling InterruptedExceptionWARNINGRestore interrupt status
CONC-008ExecutorService not shutdownERRORCall shutdown(), awaitTermination()
CONC-009Future.get() without timeoutWARNINGUse timeout to prevent deadlock
CONC-010Blocking operations in synchronized blockWARNINGUse java.util.concurrent
CONC-011Using wait()/notify() instead of java.util.concurrentWARNINGUse higher-level utilities
CONC-012Race condition in concurrent collection modificationCRITICALUse atomic operations or concurrent collections

6. Resource Management

Rule IDIssueSeverityFix
RES-001Unclosed FileInputStream/FileOutputStreamCRITICALUse try-with-resources
RES-002Unclosed database connectionsCRITICALUse try-with-resources, HikariCP
RES-003Unclosed ResultSet/StatementCRITICALUse try-with-resources
RES-004Unclosed HTTP client connectionsCRITICALUse try-with-resources, OkHttp
RES-005Unclosed streams in loopsCRITICALUse try-with-resources
RES-006Resource leak in exception pathCRITICALUse try-with-resources
RES-007InputStream/Reader not closed on exceptionWARNINGUse try-with-resources

7. Spring Framework Specific

Rule IDIssueSeverityFix
SPR-001@Transactional on private methodCRITICALMake public, use self-injection
SPR-002@Transactional without rollbackForWARNINGSpecify exception types
SPR-003Returning JPA entity to controllerWARNINGUse DTO/MapStruct
SPR-004Missing @Transactional on data operationsERRORAdd annotation
SPR-005Circular dependencyERRORUse @Lazy, refactor
SPR-006@Value on static fieldCRITICALUse setter or @Bean
SPR-007@Autowired on optional dependencyWARNINGUse constructor injection
SPR-008Missing @ComponentScan for new packagesERRORAdd package to scan
SPR-009@RequestBody without @ValidWARNINGAdd @Valid for validation
SPR-010Using @Scope("prototype") with singletonERRORUse @Scope(proxy = ...)

7.1 Spring Boot 4.x Specific (If Spring Boot 4.x detected)

Rule IDIssueSeverityFix
BOOT4-001Using @MockBean instead of @MockitoBeanWARNINGUse @MockitoBean from org.springframework.test.context.bean.override.mockito
BOOT4-002Using @SpyBean instead of @MockitoSpyBeanWARNINGUse @MockitoSpyBean from Spring Boot 4
BOOT4-003Using javax.* instead of jakarta.*ERRORMigrate all javax.* imports to jakarta.* (Jakarta EE 11)
BOOT4-004Using TestRestTemplateWARNINGUse RestTestClient in Spring Boot 4.x
BOOT4-005Using Jackson 2.x APIsWARNINGUpdate to Jackson 3.x APIs (package changes)
BOOT4-006Using Spring Security 6.x configWARNINGUpdate to Spring Security 7.x DSL
BOOT4-007Using deprecated actuator endpointsWARNINGUse new observability endpoints
BOOT4-008Using spring-boot-starter-data-* without proper test configWARNINGUpdate test configuration for Boot 4
BOOT4-009Not using spring-boot-starter-opentelemetrySUGGESTIONUse unified observability in Boot 4
BOOT4-010Missing explicit @SpringBootTest configurationWARNINGUse @TestPropertySource or properties in @SpringBootTest
BOOT4-011Using JUnit 4 assertionsWARNINGUse JUnit 5/6 assertions
BOOT4-012Using @DirtiesContext without proper handlingWARNINGBoot 4 handles test context caching better
BOOT4-013Using Spring Security 6.x lambda DSLWARNINGUpdate to Security 7.x configuration

8. Modern Java & Effective Java (Version Aware)

Rule IDIssueSeverityFixVersion
EJ-001Using StringBuilder for 1-2 concatenationsSUGGESTIONUse + for simple cases8+
EJ-002Using == on boxed primitivesWARNINGUse equals()8+
EJ-003Missing Override annotationWARNINGAdd @Override8+
EJ-004Static nested class instead of innerSUGGESTIONMake static if no outer ref8+
EJ-005Returning null instead of emptyWARNINGReturn empty collection8+
EJ-006Using raw types instead of genericsERRORUse generic type8+
EJ-007Modifying collection during iterationCRITICALUse iterator.remove()8+
EJ-008Using notify() instead of notifyAll()WARNINGUse notifyAll()8+
EJ-009Class with many static methods (not utility)SUGGESTIONConsider singleton8+
EJ-010Implementing Comparable without compareToERRORImplement fully or not at all8+
EJ-011Not using try-with-resourcesERRORUse try-with-resources9+
EJ-012Using var incorrectly (all lowercase)SUGGESTIONvar is lowercase, not Var10+
EJ-013Using var with lambda (ambiguous)WARNINGExplicit type needed10+
EJ-014String.isBlank() not usedSUGGESTIONUse String.isBlank()11+
EJ-015Files.readAllLines() not usedSUGGESTIONUse Files.readString()11+
EJ-016Using new ArrayList<>(Arrays.asList())SUGGESTIONUse List.of()9+
EJ-017Not using List.of(), Set.of(), Map.of()SUGGESTIONUse immutable collections9+
EJ-018Using Optional.isPresent() instead of orElseWARNINGUse orElseThrow(), orElse()8+
EJ-019Using Optional.get()WARNINGUse orElseThrow()8+
EJ-020Not using Stream API where appropriateSUGGESTIONConsider streams8+
EJ-021Using .forEach() with side effectsWARNINGUse for-loop if side effects8+
EJ-022Not using method referencesSUGGESTIONUse :: method references8+
EJ-023Sealed class not using permitsWARNINGAdd permits or remove sealed17+
EJ-024Using instanceof without pattern matchingWARNINGUse pattern matching16+
EJ-025Record not using canonical constructorSUGGESTIONConsider compact constructor16+
EJ-026Switch expression not usedSUGGESTIONUse switch expression14+
EJ-027Text blocks not used for multilineSUGGESTIONUse """ text blocks15+
EJ-028Not using Optional for return typesWARNINGUse Optional<T> for optional8+
EJ-029Using .map(x -> x) unnecessarilySUGGESTIONRemove unnecessary map8+
EJ-030Not using .orElseGet() for lazy defaultWARNINGUse orElseGet() for expensive ops8+
EJ-031Not using Scoped Values (JEP 506)SUGGESTIONUse ScopedValue instead of ThreadLocal25+
EJ-032Primitive patterns not used in instanceof (JEP 507)SUGGESTIONUse primitive patterns in instanceof25+
EJ-033Not using Stable Values (JEP 502)SUGGESTIONConsider StableValue for immutable caching25+
EJ-034Flexible constructor bodies not used (JEP 513)SUGGESTIONUse flexible constructor bodies25+
EJ-035Module import declarations not used (JEP 511)SUGGESTIONUse module imports for cleaner code25+
EJ-036Using traditional thread pools for I/O-bound tasksSUGGESTIONUse virtual threads (Executors.newVirtualThreadPerTaskExecutor())21+
EJ-037ThreadLocal usage without considering ScopedValueSUGGESTIONConsider ScopedValue for better inheritance25+

9. Architecture & Design

Rule IDIssueSeverityFix
ARCH-001God class (2000+ lines)ERRORSplit into smaller classes
ARCH-002Method too long (200+ lines)WARNINGExtract methods
ARCH-003Too many parameters (5+)WARNINGUse builder/DTO
ARCH-004Feature envy (class uses too much of another)WARNINGMove method to target class
ARCH-005Shotgun surgery (one change affects many)WARNINGReduce coupling
ARCH-006Duplicate codeWARNINGExtract to common method
ARCH-007Primitive obsessionWARNINGUse value objects
ARCH-008Improper package structureWARNINGFollow clean architecture
ARCH-009Circular dependency between packagesERRORRefactor, use interfaces
ARCH-010Exposing internal representationWARNINGUse encapsulation, DTOs

10. Logging & Debugging

Rule IDIssueSeverityFix
LOG-001Using System.out.println()WARNINGUse logger
LOG-002Using System.err.println()WARNINGUse logger
LOG-003Logging sensitive data (passwords, tokens)CRITICALMask before logging
LOG-004Not logging exceptions with stack traceWARNINGInclude full exception
LOG-005Logging at wrong level (info for errors)WARNINGUse appropriate level
LOG-006String concatenation in loggerWARNINGUse placeholder {}
LOG-007Not using logger for debug infoSUGGESTIONAdd debug logging

11. Testing

Rule IDIssueSeverityFix
TEST-001Missing unit tests for service layerWARNINGAdd unit tests
TEST-002Not testing exception casesWARNINGAdd exception tests
TEST-003Using @RunWith(SpringRunner.class)SUGGESTIONUse @SpringBootTest
TEST-004Test without assertionsERRORAdd assertions
TEST-005Hardcoded test dataSUGGESTIONUse test builders
TEST-006Not using @Transactional on integration testsWARNINGAdd for test isolation
TEST-007Mocking internal implementation detailsWARNINGTest via public API
TEST-008Not using @ParameterizedTestSUGGESTIONParameterize tests

12. API Design & REST

Rule IDIssueSeverityFix
API-001Using verbs in REST URLsWARNINGUse nouns, HTTP methods
API-002Not using proper HTTP status codesWARNINGUse 2xx, 4xx, 5xx correctly
API-003Exposing internal entity IDsWARNINGUse UUIDs or DTOs
API-004Not versioning APIWARNINGAdd /v1/ prefix
API-005Missing API documentationWARNINGAdd OpenAPI/Swagger
API-006No pagination on collection endpointsWARNINGAdd pagination
API-007Using POST for all operationsWARNINGUse appropriate method
API-008Not using HATEOASSUGGESTIONConsider HATEOAS
API-009Missing rate limiting on public APIsWARNINGAdd rate limiting
API-010Not using OpenAPI annotations for validationSUGGESTIONAdd @Schema, @Parameter annotations
API-011Verbose response wrappingWARNINGReturn data directly, not wrapped

13. Best Practices

Rule IDIssueSeverityFix
BP-001Magic numbers/stringsWARNINGUse constants
BP-002Not using enums for fixed valuesWARNINGUse enums
BP-003Using abbreviations in class namesWARNINGUse clear names
BP-004Not following naming conventionsWARNINGFollow Java naming
BP-005Missing Javadoc on public APISUGGESTIONAdd Javadoc
BP-006Comments describing "what" not "why"SUGGESTIONExplain rationale
BP-007Too many commentsWARNINGCode should be self-documenting
BP-008Not using Builder pattern for complex objectsSUGGESTIONUse builder
BP-009Public fields in classWARNINGUse private + accessors
BP-010Not using @Data/@Value Lombok appropriatelyWARNING@Data for entities, @Value for DTOs
BP-011Code commented out should be removedWARNINGRemove dead code, use version control
BP-012TODO/FIXME comments left in codeWARNINGComplete or create task in tracking system
BP-013Duplicate string literalsWARNINGExtract to constants
BP-014Unused imports/fields/variables/parametersWARNINGRemove dead code
BP-015Cognitive complexity too high (nested logic)WARNINGSimplify code, extract methods

14. Google Checkstyle Rules (Formatting & Style)

Based on Google Java Style Guide - checks for code formatting, naming, and style:

Rule IDIssueSeverityFix
CS-001Line length exceeds 100 charactersWARNINGBreak line at 100 chars
CS-002Missing newline at end of fileSUGGESTIONAdd trailing newline
CS-003Tab character used for indentationWARNINGUse spaces, not tabs
CS-004Wildcard imports used (e.g., import java.util.*)ERRORUse explicit imports
CS-005Imports not in alphabetical orderSUGGESTIONSort imports alphabetically
CS-006Static imports not grouped with other importsSUGGESTIONGroup static imports
CS-007Missing empty line between import groupsSUGGESTIONSeparate import groups with blank line
CS-008Incorrect brace style (not K&R)WARNINGUse K&R style braces
CS-009Missing braces for single-line statementsWARNINGAdd braces for clarity
CS-010Incorrect indentation (not +2 spaces)WARNINGUse 2-space indentation
CS-011Multiple statements on same lineWARNINGPut each statement on new line
CS-012Variable declared far from first useWARNINGDeclare variables close to usage
CS-013Wrong field naming conventionWARNINGUse lowerCamelCase for fields
CS-014Wrong method naming conventionWARNINGUse lowerCamelCase for methods
CS-015Wrong class/interface naming conventionWARNINGUse UpperCamelCase for classes
CS-016Wrong constant naming conventionWARNINGUse UPPER_SNAKE_CASE for constants
CS-017Wrong package naming conventionWARNINGUse lowercase, no underscores
CS-018Missing @Override annotationWARNINGAdd @Override when overriding
CS-019Modifier order incorrectWARNINGUse: public protected private abstract static final transient volatile synchronized native strictfp
CS-020Empty catch blockERRORLog exception or provide comment
CS-021Fall-through in switch without commentWARNINGAdd fall-through comment
CS-022Missing default in switchWARNINGAdd default case or document why not needed
CS-023Array type syntax (e.g., int[] i)WARNINGUse int[] not int i[]
CS-024Using uppercase 'L' for long literalsWARNINGUse lowercase 'l' or remove
CS-025Missing Javadoc on public classesSUGGESTIONAdd Javadoc to public classes
CS-026Missing Javadoc on public methodsSUGGESTIONAdd Javadoc to public methods
CS-027Javadoc format issuesSUGGESTIONFollow Javadoc conventions
CS-028Parameter name same as field nameWARNINGUse different name or use 'this'
CS-029Unused importWARNINGRemove unused imports
CS-030Redundant 'public' modifier on interface methodsWARNINGRemove, interface methods are implicitly public
CS-031Variable declared at top of blockWARNINGDeclare variables when first used
CS-032Long import statementsWARNINGBreak long import lines
CS-033Missing serialVersionUID in Serializable classSUGGESTIONAdd serialVersionUID field
CS-034Using System.out.printlnWARNINGUse logger instead
CS-035Magic numbers in codeWARNINGExtract to named constants

15. gRPC Java Best Practices

Load if gRPC detected: pom.xml contains grpc-java, grpc-protobuf, or .proto files exist

Rule IDIssueSeverityFix
GRPC-001Creating new ManagedChannel per requestCRITICALReuse ManagedChannel/Stubs
GRPC-002Not using keepalive pingsWARNINGEnable keepalive for long-lived connections
GRPC-003Missing connection timeoutERRORSet connection timeout
GRPC-004Not handling all gRPC status codesWARNINGHandle CANCELLED, DEADLINE_EXCEEDED, etc.
GRPC-005Using OK status with error detailsWARNINGUse proper gRPC status codes
GRPC-006Not using interceptors for authWARNINGUse ClientInterceptor/ServerInterceptor
GRPC-007Unary RPC for large payloadsWARNINGUse streaming for large data
GRPC-008Missing request validationERRORValidate in interceptor or service
GRPC-009Not using deadline/expirationWARNINGSet deadline for all calls
GRPC-010Hardcoded server addressesWARNINGUse configuration
GRPC-011Not using SSL/TLSCRITICALEnable TLS for production
GRPC-012Missing error handling in streamsERRORHandle onError properly in streaming
GRPC-013Using deprecated protobuf fieldsWARNINGUse proper proto3 features
GRPC-014Not using proto package optionWARNINGUse java_package in proto files
GRPC-015Excessive logging in gRPC methodsWARNINGUse interceptors for logging
GRPC-016Not closing gRPC resourcesCRITICALUse try-with-resources or shutdown
GRPC-017Missing circuit breaker patternSUGGESTIONAdd resilience4j for failures
GRPC-018Not using load balancingWARNINGConfigure round-robin or pick-first
GRPC-019Client blocking on streamWARNINGUse async stubs appropriately
GRPC-020Server not handling backpressureWARNINGImplement flow control

16. gRPC Security Rules

Load if gRPC detected

Rule IDIssueSeverityFix
GRPC-SEC-001No TLS/SSL encryptionCRITICALEnable TLS/SSL
GRPC-SEC-002No authentication mechanismCRITICALImplement JWT or token auth
GRPC-SEC-003Unvalidated metadata/headersERRORValidate in interceptor
GRPC-SEC-004Insecure channel credentialsERRORUse SecureChannelCredentials
GRPC-SEC-005Missing rate limitingWARNINGImplement rate limiting interceptor
GRPC-SEC-006Exposing internal service addressesWARNINGUse service mesh or proxy

17. JPA / Hibernate Rules

Load if JPA detected: pom.xml contains hibernate, spring-data-jpa, or jpa

Rule IDIssueSeverityFix
JPA-001N+1 query problemCRITICALUse JOIN FETCH
JPA-002EAGER fetching on collectionsERRORUse LAZY
JPA-003Missing @TransactionalERRORAdd @Transactional
JPA-004Returning JPA entity to controllerWARNINGUse DTO
JPA-005Missing database indexesWARNINGAdd @Index
JPA-006Large blob in entityWARNINGUse LAZY or separate table
JPA-007Entity with no version fieldWARNINGAdd @Version for optimistic locking
JPA-008Circular entity relationshipsWARNINGUse @JsonIgnore
JPA-009Native query without parameterizationERRORUse parameterized queries
JPA-010Missing cascade settingsWARNINGConfigure cascades properly

18. Lombok Rules

Load if Lombok detected: pom.xml contains lombok

Rule IDIssueSeverityFix
LOMBOK-001Using @Data on JPA entityERRORUse @Entity, @Getter, @Setter
LOMBOK-002@Data on immutable classWARNINGUse @Value
LOMBOK-003Missing @Builder.Default for non-initialized fieldsWARNINGAdd default value
LOMBOK-004Using @Getter on boolean with "is" prefixWARNINGUse proper naming
LOMBOK-005Missing @NonNull on required fieldsWARNINGAdd validation

19. Build Tools - Maven/Gradle Rules (20 rules)

Always check build files for best practices

Rule IDIssueSeverityFix
BUILD-001Using SNAPSHOT dependencies in productionCRITICALUse release versions
BUILD-002Outdated dependenciesWARNINGUpdate dependencies regularly
BUILD-003Missing dependency versions in GradleWARNINGUse version catalog or versions.toml
BUILD-004Using mavenCentral() onlySUGGESTIONConsider mavenCentral() and google()
BUILD-005Hardcoded credentials in buildCRITICALUse environment variables
BUILD-006Missing build cache configurationWARNINGEnable Gradle build cache
BUILD-007Using deprecated Gradle pluginsWARNINGUpdate to latest plugins
BUILD-008Not using dependency lockingSUGGESTIONUse dependency lock for reproducible builds
BUILD-019Missing parallel build configurationSUGGESTIONEnable parallel execution
BUILD-010Not using Gradle wrapperWARNINGUse gradle wrapper for consistency

20. Virtual Threads & Structured Concurrency (Java 21+)

Load if Java 21+ detected — checks for common pitfalls when adopting virtual threads and structured concurrency patterns.

Rule IDIssueSeverityFixVersion
VT-001synchronized block pinning virtual threadCRITICALReplace with ReentrantLock; synchronized pins the carrier thread, destroying scalability21+
VT-002ThreadLocal used with virtual threadsERRORUse ScopedValue (JEP 506) — ThreadLocal creates per-virtual-thread copies, causing memory bloat21+
VT-003Blocking I/O inside synchronized on virtual threadCRITICALExtract I/O outside synchronized block, or use ReentrantLock21+
VT-004newFixedThreadPool / newCachedThreadPool for I/O-bound tasksWARNINGUse Executors.newVirtualThreadPerTaskExecutor() for I/O-bound workloads21+
VT-005Missing StructuredTaskScope for fan-out/fan-inSUGGESTIONUse StructuredTaskScope.ShutdownOnFailure() or ShutdownOnSuccess() instead of manual CompletableFuture orchestration21+
VT-006CompletableFuture.supplyAsync() with default pool in virtual thread contextWARNINGUse StructuredTaskScope for structured lifecycle; CompletableFuture has no automatic cancellation propagation21+
VT-007Thread pool sizing for virtual threadsWARNINGDo not set pool size limits on virtual thread executors — they are lightweight and auto-scaling21+
VT-008Thread.sleep() in virtual thread without considering LockSupport.parkNanos()SUGGESTIONBoth work, but Thread.sleep() in virtual threads is fine since Java 21; flag only if inside synchronized21+
VT-009Native method / JNI call inside virtual threadWARNINGNative calls pin virtual threads to carrier; offload to platform thread pool21+
VT-010Missing try-with-resources on StructuredTaskScopeERRORAlways use try-with-resources with StructuredTaskScope to ensure subtask cleanup21+

Virtual Threads Detection Patterns:

// VT-001: synchronized pinning virtual thread (CRITICAL)
// BAD — pins the carrier thread
synchronized (lock) {
    httpClient.send(request, handler); // Blocking I/O inside synchronized!
}
// GOOD — use ReentrantLock
private final ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
    httpClient.send(request, handler);
} finally {
    lock.unlock();
}

// VT-002: ThreadLocal with virtual threads (ERROR)
// BAD — creates copy per virtual thread, memory bloat at scale
private static final ThreadLocal<UserContext> context = new ThreadLocal<>();
// GOOD — ScopedValue (Java 21+ preview, stable Java 25+)
private static final ScopedValue<UserContext> CONTEXT = ScopedValue.newInstance();
ScopedValue.where(CONTEXT, userCtx).run(() -> handleRequest());

// VT-005: Missing StructuredTaskScope (SUGGESTION)
// BAD — unstructured fan-out
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> getUser(id));
CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(() -> getOrder(id));
User user = userFuture.join();
Order order = orderFuture.join();
// GOOD — structured concurrency
try (var scope = StructuredTaskScope.ShutdownOnFailure()) {
    Subtask<User> user = scope.fork(() -> getUser(id));
    Subtask<Order> order = scope.fork(() -> getOrder(id));
    scope.join().throwIfFailed();
    return new UserOrder(user.get(), order.get());
}

// VT-010: Missing try-with-resources on StructuredTaskScope (ERROR)
// BAD — scope not auto-closed
var scope = new StructuredTaskScope.ShutdownOnFailure();
scope.fork(() -> fetchData());
scope.join();
// GOOD
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    scope.fork(() -> fetchData());
    scope.join().throwIfFailed();
}

21. Testing Depth (Extended)

Always load — comprehensive testing rules beyond the basics in Section 11.

Rule IDIssueSeverityFix
TEST-009Missing test coverage threshold in build configWARNINGAdd JaCoCo with minimum coverage (e.g., 80% line, 70% branch) in pom.xml/build.gradle
TEST-010No integration test isolation (missing Testcontainers)WARNINGUse Testcontainers for database/message-broker tests instead of H2 or embedded DBs
TEST-011Thread.sleep() in testsERRORUse Awaitility (await().atMost().until()) for async assertions — sleep causes flaky tests
TEST-012Test execution order dependencyERRORTests must be independent; remove @TestMethodOrder with @Order unless explicitly needed
TEST-013Not using @Nested for test organizationSUGGESTIONGroup related tests with @Nested inner classes for readability
TEST-014Using JUnit assertEquals instead of AssertJSUGGESTIONUse AssertJ assertThat() for fluent, readable assertions with better error messages
TEST-015Missing @DisplayName on test classes/methodsSUGGESTIONAdd @DisplayName for human-readable test names in reports
TEST-016Test data created with constructors instead of buildersWARNINGUse test data builders (Object Mother / Test Data Builder pattern) for maintainability
TEST-017No contract tests for API consumers/producersSUGGESTIONUse Spring Cloud Contract or Pact for consumer-driven contract testing
TEST-018Mocking static methods without Mockito inlineWARNINGUse mockStatic() from mockito-inline or mockito-subclass; avoid PowerMock

Testing Depth Detection Patterns:

// TEST-009: Missing JaCoCo coverage threshold
// CHECK pom.xml for:
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>check</id>
            <goals><goal>check</goal></goals>
            <configuration>
                <rules>
                    <rule>
                        <limits>
                            <limit>
                                <counter>LINE</counter>
                                <minimum>0.80</minimum>
                            </limit>
                        </limits>
                    </rule>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>
// CHECK build.gradle for:
jacocoTestCoverageVerification {
    violationRules {
        rule { limit { minimum = 0.80 } }
    }
}

// TEST-010: Testcontainers usage
// BAD — H2 behaves differently from production DB
@DataJpaTest // Uses H2 by default
class UserRepositoryTest { }
// GOOD — real database in container
@DataJpaTest
@Testcontainers
class UserRepositoryTest {
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");
}

// TEST-011: Thread.sleep() in tests (ERROR)
// BAD — flaky, wastes time
@Test
void shouldProcessAsync() {
    service.processAsync(data);
    Thread.sleep(2000); // Fragile!
    assertNotNull(repository.findResult());
}
// GOOD — Awaitility
@Test
void shouldProcessAsync() {
    service.processAsync(data);
    await().atMost(5, SECONDS).until(() -> repository.findResult() != null);
}

// TEST-012: Order-dependent tests (ERROR)
// BAD — tests depend on execution order
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class UserServiceTest {
    @Test @Order(1) void createUser() { /* creates state */ }
    @Test @Order(2) void findUser() { /* depends on createUser */ }
}
// GOOD — each test is independent
class UserServiceTest {
    @BeforeEach void setUp() { /* fresh state for each test */ }
    @Test void createUser() { }
    @Test void findUser() { /* creates its own test data */ }
}

// TEST-014: JUnit assertions vs AssertJ (SUGGESTION)
// OK but verbose
assertEquals("John", user.getName());
assertTrue(users.contains(admin));
// BETTER — AssertJ fluent API
assertThat(user.getName()).isEqualTo("John");
assertThat(users).contains(admin).hasSize(3);

22. Dead Code Detection

Detects unused code - runs in parallel with lint checks

Rule IDIssueSeverityFix
DEAD-001Unused public methodWARNINGRemove or mark with @SuppressWarnings
DEAD-002Unused private methodWARNINGRemove
DEAD-003Unused fieldWARNINGRemove
DEAD-004Unused importWARNINGRemove import statement
DEAD-005Unused local variableWARNINGRemove variable
DEAD-006Unused private constructorWARNINGRemove or make package-private
DEAD-007Unused parameterWARNINGRemove parameter or add @SuppressWarnings("unused")
DEAD-008Unused inner classWARNINGRemove or make static
DEAD-009Unreachable codeWARNINGRemove dead code
DEAD-010Duplicate codeWARNINGExtract to common method
DEAD-011Empty catch blockWARNINGAdd logging or remove
DEAD-012Empty finally blockWARNINGRemove if not needed
DEAD-013Empty constructorWARNINGRemove if class has no superclass call
DEAD-014Empty static initializerWARNINGRemove if not needed
DEAD-015Commented-out codeWARNINGRemove, use version control

Dead Code Detection Patterns:

// DEAD-001: Unused public method - may be used by reflection or external code
// Only mark as dead code if you're certain no external usage exists
public void unusedPublicMethod() { } // Check for @Api exposure first

// DEAD-004: Unused import
import java.util.List; // If List is never used

// DEAD-009: Unreachable code
public int method() {
    return 1;
    return 2; // Unreachable - remove
}

// DEAD-010: Duplicate code
public class UserService {
    public void createUser(User user) {
        validateUser(user); // Same validation duplicated
        userRepository.save(user);
        sendEmail(user.getEmail());
    }
    
    public void updateUser(User user) {
        validateUser(user); // Duplicate!
        userRepository.save(user);
    }
    
    private void validateUser(User user) { /* ... */ }
}

// DEAD-011: Empty catch block
try {
    riskyOperation();
} catch (Exception e) {
    // Empty! At least log the error
}

Review Modes

Mode 1: Local Changes (Default)

Review uncommitted changes in working directory.

git status --porcelain
git diff
git diff --cached

Mode 2: Branch Comparison

Compare feature branch against base (develop/main/master).

git branch --show-current
git diff <base-branch>..HEAD -- "*.java"
git log <base-branch>..HEAD --oneline

Mode 3: Specific Files

Analyze specific Java files.

git diff <commit> -- path/to/File.java

Install for Your Coding Agent

Teach your coding agent all Java best practice rules. Add this skill to your agent:

npx skills add ajaywadhara/java-doctor

Supports Cursor, Claude Code, Amp Code, Codex, Gemini CLI, OpenCode, Windsurf, and Antigravity.


Analysis Workflow

  1. Detect Java Version

    • Parse pom.xml or build.gradle
    • Note supported features for that version
  2. Collect Java Files

    • If reviewing changes: git diff --name-only -- "*.java"
    • If reviewing branch: git diff <base>..HEAD --name-only -- "*.java"
    • If specific files: Use user-provided paths
  3. Run Pattern Analysis

    • Use Grep to search for each rule pattern
    • Read relevant code sections for context
  4. Calculate Score

    • Start with 100
    • Deduct based on severity table
  5. Generate Report

    • Save to .output/java-doctor-{context}-{timestamp}.md

Output Format

Save reports to .output/ directory. Multiple formats available:

Format 1: Markdown (Default)

Save report to .output/java-doctor-{context}-{timestamp}.md:

# Java Doctor Report

## Summary
| Metric | Value |
|--------|-------|
| **Score** | X/100 |
| **Status** | Great / Needs Work / Critical |
| **Java Version** | X (detected from pom.xml/build.gradle) |
| **Files Analyzed** | N |
| **Issues Found** | CRITICAL: X, ERROR: X, WARNING: X, SUGGESTION: X |

## Files Analyzed
- `src/main/java/com/example/Service.java`
- `src/main/java/com/example/Controller.java`

## Issues by Category

### Security (CRITICAL)
1. **[File:Line]** - SEC-001: Hardcoded password found
   - **Severity:** CRITICAL
   - **Problem:** `private static final String PASSWORD = "********";`
   - **Fix:** Use environment variable or configuration

## Recommendations
1. Fix all CRITICAL issues immediately
2. Address ERROR issues before release
3. Review WARNING issues for improvement
4. Consider SUGGESTIONS for code quality

## Quick Fixes Available
- [ ] SEC-001: Replace hardcoded secret with @Value injection
- [ ] NULL-001: Replace .get() with orElseThrow()
- [ ] PERF-001: Add @Query with JOIN FETCH

Format 2: JSON

Save to .output/java-doctor-{context}-{timestamp}.json:

{
  "report": {
    "generated": "2024-01-15T10:30:00Z",
    "score": 85,
    "status": "Great",
    "javaVersion": "17",
    "springBootVersion": "3.2",
    "filesAnalyzed": 5
  },
  "issues": {
    "critical": [
      {
        "id": "SEC-001",
        "file": "src/main/java/com/example/AuthService.java",
        "line": 42,
        "title": "Hardcoded password found",
        "problem": "private static final String PASSWORD = \"********\";",
        "fix": "Use @Value injection or environment variable"
      }
    ],
    "error": [],
    "warning": [
      {
        "id": "NULL-001",
        "file": "src/main/java/com/example/UserService.java",
        "line": 15,
        "title": "Optional.get() without check",
        "problem": "userRepository.findById(id).get()",
        "fix": "Use .orElseThrow(() -> new NotFoundException())"
      }
    ],
    "suggestion": []
  },
  "summary": {
    "total": 12,
    "critical": 1,
    "error": 2,
    "warning": 5,
    "suggestion": 4
  }
}

Format 3: HTML Report

Save to .output/java-doctor-{context}-{timestamp}.html:

<!DOCTYPE html>
<html>
<head>
    <title>Java Doctor Report</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .score { font-size: 48px; font-weight: bold; }
        .great { color: #22c55e; }
        .needs-work { color: #eab308; }
        .critical { color: #ef4444; }
        .issue { border: 1px solid #ddd; padding: 10px; margin: 10px 0; }
        .critical-issue { border-left: 4px solid #ef4444; }
        .error-issue { border-left: 4px solid #f97316; }
        .warning-issue { border-left: 4px solid #eab308; }
    </style>
</head>
<body>
    <h1>Java Doctor Report</h1>
    <div class="score great">85/100</div>
    <p><strong>Status:</strong> Great</p>
    <p><strong>Java Version:</strong> 17</p>
    <p><strong>Files Analyzed:</strong> 5</p>
    
    <h2>Issues Found: 12</h2>
    <p>CRITICAL: 1 | ERROR: 2 | WARNING: 5 | SUGGESTION: 4</p>
    
    <h3>Critical Issues</h3>
    <div class="issue critical-issue">
        <strong>SEC-001:</strong> Hardcoded password found<br>
        <code>src/main/java/com/example/AuthService.java:42</code><br>
        Fix: Use @Value injection
    </div>
</body>
</html>

Format 4: SARIF (For IDE Integration)

Save to .output/java-doctor-{context}-{timestamp}.sarif:

{
  "version": "2.1.0",
  "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
  "runs": [{
    "tool": {
      "driver": {
        "name": "Java Doctor",
        "version": "1.0"
      }
    },
    "results": [
      {
        "ruleId": "SEC-001",
        "level": "error",
        "message": { "text": "Hardcoded password found" },
        "locations": [{
          "physicalLocation": {
            "artifactLocation": { "uri": "src/main/java/com/example/AuthService.java" },
            "region": { "startLine": 42 }
          }
        }]
      }
    ]
  }]
}

Format 5: CSV (For Excel/Sheets)

Save to .output/java-doctor-{context}-{timestamp}.csv:

Severity,Rule ID,File,Line,Issue,Problem,Fix
CRITICAL,SEC-001,src/main/java/com/example/AuthService.java,42,Hardcoded password found,"private static final String PASSWORD = \"********\";","Use @Value injection"
WARNING,NULL-001,src/main/java/com/example/UserService.java,15,Optional.get() without check,userRepository.findById(id).get(),Use orElseThrow()

Default format is Markdown. To request a different format, specify in your command:

  • "Run Java Doctor with JSON output"
  • "Generate HTML report"
  • "Export to CSV"

Effective Java Reference

Based on "Effective Java" by Joshua Bloch:

ItemTopicRelated Rules
Item 1Consider static factory methodsBP-008
Item 2Builder pattern for complex objectsBP-008
Item 3Singleton or utility classEJ-009
Item 4Enforce noninstantiabilityEJ-009
Item 5Prefer dependency injectionSPR-007
Item 6Avoid finalizersRES-001
Item 7Prefer try-with-resourcesEJ-011, RES-001
Item 8Prefer primitivesPERF-004
Item 9Avoid strings where other types appropriateARCH-007
Item 10Beware string concatenationPERF-003
Item 11Implement compareTo carefullyEJ-010
Item 12Always override toStringBP-005
Item 13Override clone judiciouslyEJ-007
Item 14Consider implementing SerializableBP-005
Item 15Minimize accessibilityARCH-010
Item 16Accessors over public fieldsBP-009
Item 17Minimize mutabilityNULL-008
Item 18Favor composition over inheritanceARCH-004
Item 19Use interfaces to define typesARCH-006
Item 20Prefer class hierarchies to tagged classesARCH-001
Item 21Use function objects (strategies)EJ-022
Item 22Favor static over nonstatic member classesEJ-004
Item 24Prefer generic typesEJ-006
Item 25Prefer lists to arraysARCH-007
Item 26Use bounded wildcardsEJ-006
Item 27Generic and可变性的取舍EJ-006
Item 28Prefer batch to discrete operationsPERF-001
Item 29Use interface for return typesAPI-003
Item 30Use checked exceptions judiciouslyEXC-003
Item 31Document checked exceptionsEXC-003
Item 32Document thread safetyCONC-001
Item 33Document synchronization policyCONC-001
Item 34Lazy initialization judiciouslyCONC-002
Item 35Don't overuse synchronizationCONC-012
Item 36Prefer executors to tasksCONC-008
Item 37Prefer concurrency utilitiesCONC-010
Item 38Check parameters for validityNULL-004
Item 39Make defensive copiesNULL-008
Item 40Design method signatures carefullyAPI-001
Item 41Use overloading judiciouslyNULL-006
Item 42Use varargs judiciouslyARCH-003
Item 43Return empty collections, not nullsNULL-003
Item 44Optional return typesEJ-018
Item 45Minimize scope of local variablesEJ-012
Item 46Prefer for-each to traditional forEJ-020
Item 47Know and use librariesPERF-012
Item 48Avoid float/double for precise calculationsBP-001
Item 49Know and use libraries (BigDecimal)BP-001
Item 50Avoid strings where other types appropriateARCH-007

---

## Interactive Workflow

After analysis, ask user what to do:

Question: "Java Doctor scan complete. Score: X/100 ({Status}). Found {N} issues." Header: "Next Steps" Options:

  • "Show me the issues" → Display all issues grouped by severity
  • "Fix critical issues" → Apply fixes for CRITICAL issues
  • "Fix all issues" → Apply fixes for all issues
  • "Save report" → Save to .output/ directory
  • "Re-scan" → Re-run analysis

---

## Quick Commands

| User Says | Your Action |
|-----------|-------------|
| "Run Java Doctor" | Full scan with version detection |
| "Scan my Java code" | Analyze local changes |
| "Check for security issues" | Focus on security rules |
| "Find performance problems" | Focus on performance rules |
| "Java code review" | Full analysis with all rules |
| "Check branch vs develop" | Branch comparison mode |
| "What's my score?" | Run scan and show score |

---

## References (Load When Needed)

- `references/bug-patterns.md` - Detailed bug patterns with code examples
- `references/security-checklist.md` - OWASP Top 10 for Java
- `references/performance-antipatterns.md` - N+1, memory, CPU issues
- `references/spring-best-practices.md` - Spring-specific rules
- `references/effective-java-mapping.md` - Items mapped to rules
- `references/version-specific-changes.md` - Java 8-21 changes
- `references/virtual-threads-guide.md` - Virtual threads & structured concurrency patterns
- `references/testing-depth-guide.md` - Testing depth rules with examples

---

This skill is inspired by react-doctor but tailored specifically for Java, incorporating best practices from "Effective Java" by Joshua Bloch and version-aware checks for Java 8 through 21.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

modern-java

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

test-ui

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated
Coding

ask-claude

Delegate a task to Claude Code CLI and immediately report the result back in chat. Supports persistent sessions with full context memory. Safe execution: no data exfiltration, no external calls, file operations confined to workspace. Use when the user asks to run Claude, delegate a coding task, continue a previous Claude session, or any task benefiting from Claude Code's tools (file editing, code analysis, bash, etc.).

Archived SourceRecently Updated