<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Todd Schiller - effect systems</title><link href="https://toddschiller.com/" rel="alternate"></link><link href="https://toddschiller.com/feeds/tag/effect-systems.atom.xml" rel="self"></link><id>https://toddschiller.com/</id><updated>2014-11-23T00:00:00-05:00</updated><subtitle>Human ✘ Artificial Intelligence</subtitle><entry><title>Enforcing memory allocation patterns with an effect system</title><link href="https://toddschiller.com/blog/java-allocation-effect-system.html" rel="alternate"></link><published>2014-11-23T00:00:00-05:00</published><updated>2014-11-23T00:00:00-05:00</updated><author><name>Todd Schiller</name></author><id>tag:toddschiller.com,2014-11-23:/blog/java-allocation-effect-system.html</id><summary type="html">&lt;p&gt;Writing performant Java software often means controlling allocation
patterns to prevent garbage collection. For example, a program for
processing
&lt;a href="https://en.wikipedia.org/wiki/Financial_Information_eXchange"&gt;financial FIX messages&lt;/a&gt;
in real-time might use a fixed buffer to avoid allocations altogether.&lt;/p&gt;
&lt;p&gt;In many cases, it's easy to determine whether code allocates
memory. However, manually verifying allocation patterns becomes …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Writing performant Java software often means controlling allocation
patterns to prevent garbage collection. For example, a program for
processing
&lt;a href="https://en.wikipedia.org/wiki/Financial_Information_eXchange"&gt;financial FIX messages&lt;/a&gt;
in real-time might use a fixed buffer to avoid allocations altogether.&lt;/p&gt;
&lt;p&gt;In many cases, it's easy to determine whether code allocates
memory. However, manually verifying allocation patterns becomes more
difficult when method calls and method overriding are involved.&lt;/p&gt;
&lt;p&gt;This post describes how to build an effect system to automatically
enforce allocation patterns. If you've programmed in Java before,
you've used an effect system: checked exceptions are an effect system.&lt;/p&gt;
&lt;h2&gt;Effect Systems&lt;/h2&gt;
&lt;p&gt;Unlike type systems, which indicate which type(s) an expression &lt;em&gt;may&lt;/em&gt;
have, effect systems indicate which effect(s) a statement or block
&lt;em&gt;may&lt;/em&gt; have. For example, the following method has the effect that it
&lt;em&gt;may&lt;/em&gt; throw a &lt;code&gt;FileNotFoundException&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;maybeThrow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FileNotFoundException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The method above &lt;em&gt;may&lt;/em&gt; throw the exception — or it &lt;em&gt;may
not&lt;/em&gt;. It's perfectly legal to annotate an empty method as potentially
throwing an exception!&lt;/p&gt;
&lt;p&gt;The compiler enforces that the caller of a method either: (1)
handles the exception with a &lt;code&gt;catch&lt;/code&gt; block, or (2) declares that it
might also throw the exception (or a supertype of the exception).&lt;/p&gt;
&lt;h2&gt;Enforcing Allocation Patterns&lt;/h2&gt;
&lt;p&gt;For enforcing allocation patterns, we'd like to do something
similar. The developer should be able to annotate which methods may
allocate memory. Fortunately, the ability to define method annotations
has existed since Java 1.5:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@MayAlloc&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mayAlloc&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;More interestingly, the developer should be able to annotate which
methods should not allocate memory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@NoAlloc&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;safeMethod&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Based on these annotations, we'd like the compiler to check that no
method marked as &lt;code&gt;@NoAlloc&lt;/code&gt; ever (1) itself allocates memory, or (2)
calls a method that directly or indirectly allocates memory.&lt;/p&gt;
&lt;p&gt;To make the compiler perform these checks, we'll use the
&lt;a href="http://checkerframework.org"&gt;Checker Framework&lt;/a&gt;, a tool for defining
custom Java type systems. It's designed to take advantage of the new
&lt;a href="http://www.infoq.com/articles/Type-Annotations-in-Java-8"&gt;Type Annotations feature in Java 8&lt;/a&gt;.
However, to implement a basic allocation effect system, we'll just use
method annotations.&lt;/p&gt;
&lt;p&gt;The full checker implementation
is &lt;a href="https://github.com/twschiller/alloc-effect-checker"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Defining Annotations&lt;/h3&gt;
&lt;p&gt;First we'll define the annotations &lt;code&gt;@MayAlloc&lt;/code&gt; and &lt;code&gt;@NoAlloc&lt;/code&gt; that the
developer can write on method declarations:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ElementType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;METHOD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MayAlloc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ElementType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;METHOD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NoAlloc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since we're using the Checker Framework, we also have to define a type
annotation for the default checker to process. For our checker, we'll
just define a type annotation &lt;code&gt;@EffectType&lt;/code&gt; that we'll tell the
Checker Framework to apply everywhere:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@TypeQualifier&lt;/span&gt;
&lt;span class="nd"&gt;@DefaultQualifierInHierarchy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Apply the annotation automatically&lt;/span&gt;
&lt;span class="nd"&gt;@SubtypeOf&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// The annotation is not related to anything else&lt;/span&gt;
&lt;span class="nd"&gt;@ImplicitFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trees&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NULL_LITERAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ElementType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TYPE_USE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ElementType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TYPE_PARAMETER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EffectType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For some effect systems, it is beneficial to define additional type
annotations. See the Checker Framework's
&lt;a href="http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html#guieffect-checker"&gt;GUI Effect Checker&lt;/a&gt;
as an example.&lt;/p&gt;
&lt;h3&gt;Creating a Checker&lt;/h3&gt;
&lt;p&gt;Now that we've defined our annotations, we can define a checker &lt;code&gt;AllocEffect&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@TypeQualifiers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EffectType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Don&amp;#39;t list the method annotations&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AllocEffectChecker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BaseTypeChecker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Every checker has two main parts. The &lt;em&gt;Type Factory&lt;/em&gt; populates
annotations on methods and types. The &lt;em&gt;Visitor&lt;/em&gt; checks that the
annotations are consistent, and that the code is consistent with
the annotations. Using the Checker Framework naming convention, the
type factory and visitor for our checker will be called
&lt;code&gt;AllocEffectTypeFactory&lt;/code&gt; and &lt;code&gt;AllocEffectVisitor&lt;/code&gt;, respectively.&lt;/p&gt;
&lt;h3&gt;The Annotation Factory&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;AllocEffectTypeFactory&lt;/code&gt; will compute annotations for methods that
don't have developer-written annotations. Our factory will follow two
rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If a method is unannotated, add the &lt;code&gt;@MayAlloc&lt;/code&gt; annotation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If an unannotated method overrides another method, inherit the
annotation(s) from the overridden methods. If the developer writes a
&lt;code&gt;@MayAlloc&lt;/code&gt; annotation on a method overridding a method declared
as &lt;code&gt;@NoAlloc&lt;/code&gt;, emit a warning.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To enforce the second rule, we'll have the checker compute the range
of effects each method can have based on the Java type
hierarchy. Computing a range is overkill for an effect system with
just 2 effects, but it provides a good basis for adding new features
to the checker.&lt;/p&gt;
&lt;p&gt;To define a range of effects, we have to define the relationship
between each effect. Typically we'll use a hierarchy, just like in the
standard Java type system. The two effects &lt;code&gt;@NoAlloc&lt;/code&gt; and &lt;code&gt;@MayAlloc&lt;/code&gt;
have the following subtyping relation:&lt;/p&gt;
&lt;div style="text-align:center; margin-bottom: 10px;"&gt;
&lt;img loading="lazy" decoding="async"
  src="/assets/alloc-effect-hierarchy.png"
  alt="Allocation Effect System type hierarchy" /&gt;
&lt;/div&gt;
&lt;p&gt;There's two ways to think about this. First, the set of methods that
&lt;em&gt;may or may not&lt;/em&gt; allocate memory must be a superset of the methods
which &lt;em&gt;may not&lt;/em&gt; allocate memory. Conversely, the &lt;code&gt;@NoAlloc&lt;/code&gt; annotation
provides a strictly stronger guarantee than the &lt;code&gt;@MayAlloc&lt;/code&gt;
annotation.&lt;/p&gt;
&lt;p&gt;To check whether an operation (e.g., method call) is valid, we'll use
a method &lt;code&gt;checkEffect&lt;/code&gt; to check whether the operation's effect is a
subtype of the effect of the method it's being called from. If not,
we'll have Check Framework emit a warning:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;checkEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;callerEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;targetEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetEffect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callerEffect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// The target effect is a supertype of the effect of the enclosing method&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// The message call.invalid.alloc is defined in a .properties file&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;checker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;call.invalid.alloc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;targetEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;callerEffect&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;	               &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;The Annotation Checker&lt;/h3&gt;
&lt;p&gt;Now that each method has an annotation, we'll define a checker
&lt;code&gt;AllocEffectVisitor&lt;/code&gt; to enforce the annotations. There are three rules
we want to enforce:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If a method with a &lt;code&gt;@NoAlloc&lt;/code&gt; annotation uses the &lt;code&gt;new&lt;/code&gt;
operator, emit a warning.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If a method with a &lt;code&gt;@NoAlloc&lt;/code&gt; annotation calls a method with the
&lt;code&gt;@MayAlloc&lt;/code&gt; annotation, emit a warning.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the developer has written both &lt;code&gt;@MayAlloc&lt;/code&gt; and &lt;code&gt;@NoAlloc&lt;/code&gt; on
a method, emit a warning.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using these rules, it's always safe for a method to call another
method that has the &lt;code&gt;@NoAlloc&lt;/code&gt; annotation.&lt;/p&gt;
&lt;p&gt;The Checker Framework's visitor implementation, &lt;code&gt;BaseTypeVisitor&lt;/code&gt;,
recursively visits each node in the program's Abstract Syntax Tree. To
enforce the first rule, we'll override the &lt;code&gt;visitNewArray&lt;/code&gt; and
&lt;code&gt;checkConstructorInvocation&lt;/code&gt; visitor methods. Our implementation will
check that the enclosing method has the &lt;code&gt;@MayAlloc&lt;/code&gt; annotation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;visitNewArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewArrayTree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// The &amp;#39;new&amp;#39; operator is just like a method that has a @MayAlloc annotation&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;targetEffect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MayAlloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Get the annotation for the enclosing method&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;MethodTree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;callerTree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TreeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enclosingMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getCurrentPath&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ExecutableElement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;callerElt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TreeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;elementFromDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callerTree&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Make sure the two effects are consistent. That is, that target&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// effect is a subtype of the calling effect. Because the&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// targetEffect is @MayAlloc, this checks that the method&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// annotation is @MayAlloc too.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;checkEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callerEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;targetEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;visitNewArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To enforce the second rule, we'll override the &lt;code&gt;visitMethodInvocation&lt;/code&gt;
method. The implementation is the same, except we use the effect of
the method being called:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;visitMethodInvocation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MethodInvocationTree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Get the annotation for the method being called&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ExecutableElement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;methodElt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TreeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;elementFromUse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;targetEffect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atypeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclaredEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;methodElt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// ... same as for visitNewArray(...)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To enforce the third rule, we'll override the &lt;code&gt;visitMethod&lt;/code&gt; method to
report an error if a method has both a &lt;code&gt;@MayAlloc&lt;/code&gt; and &lt;code&gt;@NoAlloc&lt;/code&gt;
annotation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;visitMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MethodTree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ExecutableElement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;methElt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TreeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;elementFromDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;AnnotationMirror&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mayAlloc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atypeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclAnnotation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;methElt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MayAlloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;AnnotationMirror&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;noAlloc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atypeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclAnnotation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;methElt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NoAlloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mayAlloc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;noAlloc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;checker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;annotations.conflicts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;visitMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Running the Checker&lt;/h3&gt;
&lt;p&gt;At this point, we've built a basic checker for memory allocations. You can
&lt;a href="https://github.com/twschiller/alloc-effect-checker"&gt;download the full implementation on GitHub&lt;/a&gt;.
To run the
checker,
use &lt;code&gt;javac&lt;/code&gt; with the &lt;code&gt;-processor&lt;/code&gt; argument and the checker on the
classpath (setting the classpath with the &lt;code&gt;-cp&lt;/code&gt; flag, as necessary):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:::bash
javac -processor com.toddschiller.checker.AllocEffectChecker com/toddschiller/experiments/AllocationEffects.java
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The implementation on GitHub also supplies a debug mode, which you
can enable by passing the &lt;code&gt;-Alint=debugSpew&lt;/code&gt; flag to the compiler. The
debug mode reports each check performed by the checker.&lt;/p&gt;
&lt;p&gt;For the example file &lt;code&gt;AllocationEffects.java&lt;/code&gt;,
the checker reports 6 warnings. The two assignments&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@NoAlloc&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;shouldWarn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mayAllocateMemory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// an unannotated method&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;are both flagged by the checker:&lt;/p&gt;
&lt;!-- markdownlint-disable MD013 --&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;AllocationEffects.java:42: error: [call.invalid.alloc] Calling a method with MayAlloc effect from a context limited to NoAlloc effects.
            int i = new Integer(2);
                    ^
AllocationEffects.java:56: error: [call.invalid.alloc] Calling a method with MayAlloc effect from a context limited to NoAlloc effects.
        int x = mayAllocateMemory();
                                 ^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!-- markdownlint-enable MD013 --&gt;
&lt;h2&gt;Improving the Checker&lt;/h2&gt;
&lt;p&gt;Now that we've implemented a basic checker, there's two important questions to
ask:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Can the checker emit a warning even when the program won't allocate
memory (false positives)?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;More importantly, are there any allocations that the checker will
fail to report (false negatives)?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Eliminating False Warnings&lt;/h3&gt;
&lt;p&gt;The first question is easier to answer — of course! Just like
the Java type checker, our checker doesn't consider values or control
flow:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;conditionallyAlloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doAlloc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@NoAlloc&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;noAlloc&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;conditionallyAlloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// WARNING!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at the implementation of &lt;code&gt;conditionallyAlloc&lt;/code&gt;, we ideally
wouldn't get a warning. But, if we were to write an annotation for the
the &lt;code&gt;conditionallyAlloc&lt;/code&gt; method, what would we write? Unfortunately
our vocabulary of just &lt;code&gt;@NoAlloc&lt;/code&gt; and &lt;code&gt;@MayAlloc&lt;/code&gt; is insufficient.&lt;/p&gt;
&lt;p&gt;One way to solve the problem would be to let the developer write an
annotation &lt;code&gt;@MayAllocIf(&amp;quot;alloc&amp;quot;)&lt;/code&gt;, referring to the boolean &lt;code&gt;alloc&lt;/code&gt;
parameter. While we could modify the checker to support this
particular annotation, we quickly run into a wall trying to support other
expressions — we'd have to figure out how to verify arbitrary
logic at compile-time!&lt;/p&gt;
&lt;p&gt;In this case, a reasonable solution might be to ignore the warning by
adding an &lt;code&gt;@SuppressWarnings(&amp;quot;alloceffect&amp;quot;)&lt;/code&gt; annotation to the
call to &lt;code&gt;conditionallyAlloc&lt;/code&gt;. (&amp;quot;alloceffect&amp;quot; is the name of the checker in
lower-case).&lt;/p&gt;
&lt;p&gt;However, in many cases, it is better to refactor the code. Code that a
checker can reason about is generally also easier for a human developer to
reason
about.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Can you think of other cases for which the checker will issue false
warnings? Are there common patterns (e.g., the singleton pattern) where it would
make sense to
introduce special annotations?&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Identifying All Allocations&lt;/h3&gt;
&lt;p&gt;Identifying allocations that the checker will miss is trickier —
are all allocations the result of the &lt;code&gt;new&lt;/code&gt; keyword?&lt;/p&gt;
&lt;p&gt;Ignoring reflection and system calls, the answer appears to be
&amp;quot;yes&amp;quot;. However, some uses of &lt;code&gt;new&lt;/code&gt; can be obfuscated. Consider a class
with a static field and a method that accesses that field:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AllocOnLoad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;five&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// The static initializer can contain arbitrary code&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;five&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nd"&gt;@NoAlloc&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;addFive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AllocOnLoad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;five&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Warning?&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When the program runs, if a call to &lt;code&gt;addFive&lt;/code&gt; is the first time the
&lt;code&gt;AllocOnLoad&lt;/code&gt; class if referenced during the execution, the static
initializer will run and memory will be allocated. On all
subsequent calls, no memory will be allocated.&lt;/p&gt;
&lt;p&gt;To catch this behavior, the developer would need annotate classes with
whether or not their static initializer may allocate memory. The
checker could then treat class references similar to method calls.&lt;/p&gt;
&lt;p&gt;The problem with this approach is that it would lead to a lot of false
positives. A potential solution would be to allow the developer to
specify that certain classes have already been loaded when a method is
called, à la:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@NoAlloc&lt;/span&gt;
&lt;span class="nd"&gt;@RequireLoaded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;AllocOnLoad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;addFive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AllocOnLoad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;five&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Safe!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Implementing such a system would involve introducing an effect system
to track which classes each method loads. The difference is that the
effect system would need to track which classes &lt;em&gt;must&lt;/em&gt; have been
loaded. For example, the &lt;code&gt;addFive&lt;/code&gt; method would have the effect
&lt;code&gt;@Loads({AllocOnLoad.class})&lt;/code&gt; because the method &lt;em&gt;always&lt;/em&gt; references
the &lt;code&gt;AllocOnLoad&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;Writing down which classes a method &lt;em&gt;must&lt;/em&gt; load is tedious and
error-prone. The developer has to consider all the classes
transitively referenced by the method. Therefore, this information
would be a good candidate for automatic inference.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Can you think of other cases where the checker would miss an
allocation? What happens when you concatenate two strings: str1 + str2?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This post described an effect system for enforcing memory allocation
patterns. We introduced two method annotations, &lt;code&gt;@MayAlloc&lt;/code&gt; and
&lt;code&gt;@NoAlloc&lt;/code&gt;, to describe the effect of each method. We then used the
&lt;a href="http://checkerframework.org"&gt;Checker Framework&lt;/a&gt; to enforce that no
memory allocations are either directly or indirectly performed by
methods marked as &lt;code&gt;@NoAlloc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more information about implementing effect systems with the
Checker Framework, check out the framework's
&lt;a href="http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html#guieffect-checker"&gt;GUI Effect Checker&lt;/a&gt;,
which checks for UI threading errors. Unlike the basic checker we
built, it makes use of the Checker Framework's type annotation
features to support common UI programming idioms.&lt;/p&gt;
&lt;p&gt;The source code for the allocation checker is available on GitHub
at: &lt;a href="https://github.com/twschiller/alloc-effect-checker"&gt;https://github.com/twschiller/alloc-effect-checker&lt;/a&gt;&lt;/p&gt;
</content><category term="Verification"></category><category term="verification"></category><category term="java"></category><category term="effect systems"></category><category term="Checker Framework"></category></entry></feed>