We're updating the issue view to help you get more done. 

If you AOT protocol call sites, then you will also need to AOT the protocol itself


Closed as not a bug--Happy to help improve the usability of the advice below. (@stuarthalloway Sept 2017)


  • Clojure's DynamicClassLoader allows Clojure code (including Java classes) to be dymamically reloaded during development.

  • Clojure allows Ahead-Of-Time (AOT) compilation into class files. AOTed code will e.g. load faster but does not support the dynamic reloading approach described above.

  • Clojure protocols provide fast dispatch by creating a Java interface, and by directly using that Java interface at protocol call sites.

  • Java's classloader delegation model means that protocol call sites must be able to "see" protocol implementations via the classloader delegation.


If you have an AOTed protocol call site, you must also AOT the protocol itself. This is irritating, but it is not a bug. It is a predictable consequence of the design choices above, but it is surprising because the Java-level symptom stems not from something you did directly, but from an implementation detail of protocols.

A minimal reproducible case is described in the following comment: http://dev.clojure.org/jira/browse/CLJ-1544?focusedCommentId=36734&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-36734

Other examples:

A real issue triggered by this bug: https://github.com/cemerick/austin/issues/23

Avoiding the Problem:

If you have an AOT compiled protocol call site, make sure that you AOT the protocol itself. This is true regardless of when the problem occurs, e.g. dev-time vs. build-time vs. runtime. Build-space tools could be augmented to be smart about this, e.g. detect the situation, show what needs to be compiled, etc.

Not a Problem:

Some of the repros attached to this ticket show a similar symptom when trying to directly use defrecord or deftype class names, e.g.


Deftype/defrecord references can and should be avoided by looser coupling: Instead of naming the deftype or defrecord class directly, use a factory function. Note that deftype and defrecord always make a factory function for you.


This ticket includes a patch that papers over the issue by magically reloading namespaces during AOT compilation if no matching classfile is found in the compile-path or in the classpath. This "cure" would be worse than the disease.

Related ticket: CLJ-1641 contains descriptions and comments about some potentially unwanted consequences of applying proposed patch 0001-CLJ-1544-force-reloading-of-namespaces-during-AOT-co-v3.patch







Allen Rohner






Fix versions