Presentation on JSR-305

172 views
Skip to first unread message

Bill Pugh

unread,
May 27, 2008, 3:35:43 PM5/27/08
to jsr...@googlegroups.com
OK, the following is a fairly complete presentation on what I'd like
to propose for JSR-305.

http://www.cs.umd.edu/~pugh/JSR-305.pdf

I will be posting a survey about many of the issues described in it
shortly.

Bill


Dave Griffith

unread,
May 27, 2008, 7:10:01 PM5/27/08
to JSR-305: Annotations for Software Defect Detection

This is the first I've seen of the exclusive values stuff or the type
validators. Very pretty, and a good generalization of a lot of other
ideas that have been floated (i.e. @StaticResource, @MatchesPattern).
It takes a bit of faith to actually implement such analyses in an IDE
or other static checking tool, as it means that valid user code can
crash/hang your tool.

The exclusive values and type validators work brings up an issue,
though. A static analyzer can only check for exclusive/exhaustive
values if the values are compile-time constant expressions. Should
there be an annotation for parameters which should only be compile-
time constant expressions? This might be valuable for
something .prepareStatement(), as a scorched-earth way of preventing
SQL injection attacks on a code-base, but possibly only for highly
risk-averse applications.

Jens Voß

unread,
May 28, 2008, 5:57:04 AM5/28/08
to JSR-305: Annotations for Software Defect Detection
Hi Bill,

The Type Qualifier stuff looks really cool! Any estimate on when an
Early Draft of the JSR might be ready? Is it still realistic to hope
for inclusion in JavaSE 7.0?

Best regards,
Jens

BTW, I think I spotted a typo on page 37 where the first line of the
included code should read
public @TypeQualifier(exhaustive=true)
(rather than "exclusive=true").

Bill Pugh

unread,
May 28, 2008, 10:20:29 AM5/28/08
to jsr...@googlegroups.com

On May 27, 2008, at 7:10 PM, Dave Griffith wrote:

> This is the first I've seen of the exclusive values stuff or the type
> validators. Very pretty, and a good generalization of a lot of other
> ideas that have been floated (i.e. @StaticResource, @MatchesPattern).
> It takes a bit of faith to actually implement such analyses in an IDE
> or other static checking tool, as it means that valid user code can
> crash/hang your tool.

The only annotation code that would be executed inside static analysis
tools would be Validators, and validators should be executed within a
security manager.

Michael Ernst has proposed some even more extensive capabilities in
compiler plugins built on top of JSR-308. These are also very cool,
but require that the plugins be written to specific API's for the
abstract symbol tree and other compiler internals. As such, they
wouldn't be portable across different IDE's and wouldn't be
appropriate for JSR-305.

http://groups.csail.mit.edu/pag/jsr308/


> The exclusive values and type validators work brings up an issue,
> though. A static analyzer can only check for exclusive/exhaustive
> values if the values are compile-time constant expressions. Should
> there be an annotation for parameters which should only be compile-
> time constant expressions? This might be valuable for
> something .prepareStatement(), as a scorched-earth way of preventing
> SQL injection attacks on a code-base, but possibly only for highly
> risk-averse applications.

Although that would be useful in some cases, I think the call for it
would be fairly limited, and probably wouldn't make the cut for
JSR-305. It could be implemented for a specific static analysis tool
if you thought it useful, and if it catches on it could be added to
JSR-305 later.

Bill

Bill Pugh

unread,
May 28, 2008, 10:38:05 AM5/28/08
to jsr...@googlegroups.com

On May 28, 2008, at 5:57 AM, Jens Voß wrote:

>
> Hi Bill,
>
> The Type Qualifier stuff looks really cool! Any estimate on when an
> Early Draft of the JSR might be ready? Is it still realistic to hope
> for inclusion in JavaSE 7.0?

We have large portions of this implemented in FindBugs. If we can get
agreement on what has been proposed, we should have a full
implementation and an official draft ready in a month or two.


> Best regards,
> Jens
>
> BTW, I think I spotted a typo on page 37 where the first line of the
> included code should read
> public @TypeQualifier(exhaustive=true)
> (rather than "exclusive=true").

Thanks, fixed.

Bill

Dave Griffith

unread,
May 28, 2008, 10:45:45 AM5/28/08
to JSR-305: Annotations for Software Defect Detection

> The only annotation code that would be executed inside static analysis
> tools would be Validators, and validators should be executed within a
> security manager.

Sure, and that will stop a lot of possible maliciousness, but won't
prevent validators from crashing or hanging the tools. I can
absolutely believe the industry is ready for this technology (I've
thought of about twenty use cases for it in just the last day), but
the security issues are worth noting.

Michael Ernst

unread,
May 29, 2008, 4:09:38 PM5/29/08
to jsr...@googlegroups.com
> Michael Ernst has proposed some even more extensive capabilities in
> compiler plugins built on top of JSR-308.
> http://groups.csail.mit.edu/pag/jsr308/

More specifically, we have had a publicly available implementation of
user-defined type qualifiers since January 2007. Our type-qualifier
checkers have run on over 600,000 lines of code (that we know of).

> These are also very cool,
> but require that the plugins be written to specific API's for the
> abstract symbol tree and other compiler internals.

The latter part of the statement isn't quite right.

Our Checker Framework lets you define checkers for straightforward type
qualifiers without writing any code at all. The Basic Checker (also known
as the "Custom Checker") reads the semantics for the type qualifiers out of
annotations. For example, our implementation makes use of a @TypeQualifier
meta-annotation, just like Bill's proposal. The approaches differ in other
ways, however.

> As such, they
> wouldn't be portable across different IDE's and wouldn't be
> appropriate for JSR-305.

If you want to do sophisticated processing of powerful type qualifiers,
then there is no way to avoid accessing the Java syntax via an abstract
syntax tree (AST). You can avoid using compiler internals via use of the
standard AST of JSR 198, Extension API for Integrated Development
Environments. Our current implementation does not use JSR 198. It works
as a plugin to javac and, like other bug-finding tools, can be invoked as
an external tool by an IDE.

You can download the implementation at

http://groups.csail.mit.edu/pag/jsr308/

You can also read a technical paper about the Checker Framework. It is
titled "Practical pluggable types for Java" and will appear at the ISSTA
2008 conference this summer.

http://people.csail.mit.edu/mernst/pubs/pluggable-checkers-issta2008-abstract.html
http://people.csail.mit.edu/mernst/pubs/pluggable-checkers-issta2008.pdf

-Mike

Brian Goetz

unread,
Jun 5, 2008, 1:38:20 PM6/5/08
to jsr...@googlegroups.com
(Warning: I've raised this point before.)

I still worry that default annotations are extrapolating, somewhat
dangerously, from one example. The canonical case is nullness, and there's
empirical data that shows that most APIs assume most parameters are non-null.
So having "default is non-null" makes sense. Are there other defaults that
make sense?

Brian Goetz

unread,
Jun 5, 2008, 1:44:14 PM6/5/08
to jsr...@googlegroups.com
Re: @OverridingMethodsMustInvokeSuper

It may be useful to specify whether super should be invoke before or after the
subclass method (CLOS does this.)

Bill Pugh

unread,
Jun 5, 2008, 5:02:39 PM6/5/08
to jsr...@googlegroups.com
In FindBugs, we need to deal with the fact that some API's use dotted
class names (Java source level names)
and others use slashed class names (JVM class names). Getting these
confused is bad. So we have @DottedClassName and @SlashedClassName
type qualifiers.

A particular class or package generally uses one or the other. For
example, BCEL mostly uses dotted class names, and ASM mostly uses
slashed class names. Being able to specify a default at a package or
class level is useful.

I wouldn't be surprised if a number of API's took nonnegative integers
by default.

I've tried to make it so that the ability to define custom default
type qualifiers is a compartmentalized feature that won't really be
visible or obvious unless you look for it. Some of my earlier attempts
at doing this required stuff that was visible every time you defined a
type qualifier that you wanted to be able to use as a default, and I
wasn't happy with it.

Gregory Kick

unread,
Jun 5, 2008, 6:21:15 PM6/5/08
to jsr...@googlegroups.com
@Brian
I'd had a similar thought about defaults, and was wondering if it's
reasonable to pick a default at all. The empirical evidence shows
that most APIs assume non-null, but if you're writing one that doesn't
you are constantly having to override the default. Could
package-level annotations that allow you to define defaults solve that
problem without any extrapolation?

--
Gregory Kick
http://kickstyle.net/

Bill Pugh

unread,
Jun 5, 2008, 7:03:12 PM6/5/08
to jsr...@googlegroups.com
Gregory,
I'm not quite sure what your question is.

Unless there is an inherited type qualifier, or a default type
qualifier that derives from an explicit annotation on a surround
scope, it is treated as being unannotated, which is the same as a type
qualifier with when=When.UNKNOWN.

So, for example, if you didn't say anything about the default
nullness of method parameters at a package, class or method level,
then each method parameter would be treated as a nullness parameter
only if explicitly so annotated.

On the other hand, you could put a annotation on a package saying
that parameters are nonnull by default, and then override that on some
specific classes with a annotation saying that parameters have unknown
nullness by default.

Can you try explaining your concern in more detail, so I can try to
answer it better?

Bill

Bill Pugh

unread,
Jun 5, 2008, 9:48:51 PM6/5/08
to jsr...@googlegroups.com
I've thought about that. The question is, will it pull it's own
weight? Said another way,
of the times you want have a method call the overridden method, what
percentage of the
time do you want it to always do so at the beginning or end?

Also, if you want it do be done first, do you really need it to be the
very first thing in the method? What
if the overriding method logs a message, tests for illegal arguments,
or obtains a lock first,
before the call to super? Is that a violation?

Bill

Michael Ernst

unread,
Jun 6, 2008, 3:31:07 AM6/6/08
to jsr...@googlegroups.com
> I'd had a similar thought about defaults, and was wondering if it's
> reasonable to pick a default at all.

I generally agree that being able to specify defaults is useful:
universally and at a package/class level. (I'm not so convinced about
methods, but it seems reasonable to permit that for uniformity.)

Users of the Checker Framework (available at
http://groups.csail.mit.edu/pag/jsr308/) have found that there are defaults
that make sense for non-nullness qualifiers. And different code may
requires different defaults (even for nullness qualifiers).

However, let me answer Brian's question about a nullness type system in
specific.

> there's
> empirical data that shows that most APIs assume most parameters are non-null.
> So having "default is non-null" makes sense. Are there other defaults that
> make sense?

There is another default for nullness that makes sense: "non-null except
locals", or "NNEL". This is explained in the ISSTA 2008 paper "Practical
Pluggable Types for Java":
http://people.csail.mit.edu/mernst/pubs/pluggable-checkers-issta2008.pdf

Below I've excerpted section 6.1 of the paper, which discusses the non-null
except locals (NNEL) default.

-Mike


6.1 Default annotation for Nullness checker

The Nullness checker treats unannotated local variables as Nullable,
and all other unannotated types (including generic type arguments
on local variables) as non-null. We call this default NNEL,
for NonNull Except Locals. The NNEL default reduces the programmer's
annotation burden, especially in conjunction with the
flow-sensitive type inference of Section 3.7. The default can be
overridden on a class, method, or field level.

We believe the NNEL design for defaults to be novel, and our experience
indicates that it is superior to other choices. NNEL combines
the strengths of two previously-proposed default systems:
nullable-by-default and non-null-by-default.

Nullable-by-default has the advantage of backward-compatibility,
because an ordinary Java variable may always be null.

Non-null-by-default reduces clutter because non-null types are
more prevalent, and it is good to bias programmers away from using
nullable variables. Splint, Nice, JML, and Eiffel have adopted nonnull-
by-default semantics.

To evaluate the defaults, the programmer annotated subject programs
multiple times, using different defaults. (Since the type system
and checker are unchanged, the checker warnings indicated
exactly the same errors regardless of the annotation default.) We
are not aware of any previous study that quantifies the difference
between using nullable-by-default and non-null-by-default, though
Chalin and James [5] determined via manual inspection that about
3/4 of variables in JML code and the Eclipse compiler are dereferenced
without being checked.

Figure 4 shows our results. The NNEL code was not just
terser, but -- more importantly -- clearer to the programmers in our
study. Reduced clutter directly contributes to readability. Our
choice of the NNEL default was also motivated by the observation
that when using nullable-by-default, programmers most often
overlooked @NonNull annotations on generic types; the NNEL default
corrects this problem. A potential downside of non-uniform
defaults is that an unannotated type such as "Integer" means different
things in different parts of the code, but this was not a problem
in practice, perhaps because programmers think of public declarations
differently than private implementations. Further use in
practice will yield more insight into the benefits of the NNEL default.
We believe that the general approach embodied by the NNEL
default is also applicable to other type systems.

FIGURE 4:

| Nullable | NonNull | NNEL
Program | Tot Sig Body | Tot Sig Body | Tot Sig Body
-------------------------------------------------------------------
Annotation file utils | 760 483 277 | 165 86 79 | 107 90 17
Lookup | 382 301 81 | 78 31 47 | 35 33 2
Nullness checker | - - - | 282 126 156 | 146 126 20

Figure 4: The number of annotations required to eliminate null
dereference warnings, depending on the default for nullity annotations.
The total number of annotations ("Tot") is the sum of those
in method/field signatures ("Sig") plus those in method/initializer
bodies ("Body").

Brian Goetz

unread,
Jun 6, 2008, 9:55:46 PM6/6/08
to jsr...@googlegroups.com
> However, let me answer Brian's question about a nullness type system in
> specific.
>
>> there's
>> empirical data that shows that most APIs assume most parameters are non-null.
>> So having "default is non-null" makes sense. Are there other defaults that
>> make sense?
>
> There is another default for nullness that makes sense: "non-null except
> locals", or "NNEL". This is explained in the ISSTA 2008 paper "Practical
> Pluggable Types for Java":
> http://people.csail.mit.edu/mernst/pubs/pluggable-checkers-issta2008.pdf
>
> Below I've excerpted section 6.1 of the paper, which discusses the non-null
> except locals (NNEL) default.

Interesting information. But I think I phrased the question wrong. Are there
other annotations _besides nullness_ for which having default annotations is
really compelling? Every time the topic comes up, people say "but you
wouldn't want to have to type @NonNull everywhere." If the nullness problem
went away, would there be a compelling next candidate for why we want default
annotations in general?

Sorry to be a broken record but this really pushes my "feels like
extrapolating from one example" button and such things tend to be both more
complex and less useful than initially hoped.

Michael Ernst

unread,
Jun 6, 2008, 11:23:22 PM6/6/08
to jsr...@googlegroups.com
Brian-

> Every time the [annotation defaults] topic comes up, people say "but you

> wouldn't want to have to type @NonNull everywhere."

I don't think this is a fair characterization, given the messages on this
mailing list in the last few days.

> Are there
> other annotations _besides nullness_ for which having default annotations is
> really compelling?

Bill Pugh gave this example yesterday in response to your message:

In FindBugs, we need to deal with the fact that some API's use dotted
class names (Java source level names)
and others use slashed class names (JVM class names). Getting these
confused is bad. So we have @DottedClassName and @SlashedClassName
type qualifiers.

A particular class or package generally uses one or the other. For
example, BCEL mostly uses dotted class names, and ASM mostly uses
slashed class names. Being able to specify a default at a package or
class level is useful.

Bill also speculated about interfaces that take nonnegative numbers most
frequently.

The part of my message that you didn't quote said that even for qualifiers
that are not nullness-related, users of our tools have found defaults
useful. (I didn't give examples, because it didn't seem to be necessary.)

A specific example is immutability. In our case studies, we have found
that some code is written in a mostly-functional style (creates new
objects), and some code is written in a mostly-side-effecting style (fields
get updated). Different defaults are needed to minimize the number of
annotations in different code.

As another example, some code is thread-safe and some is not. Different
defaults might be useful there.

In addition to these, our new NNEL default for nullness illustrates that it
would be a bad idea to bake one default into a type system, because you
might get it wrong -- even if you were only considering nullness. (Given
all the interest in nullness checking so far, it's surprising that the
previous default choices are so much worse than the new NNEL default.)
It's better to permit experimentation -- and, more importantly, flexibility
to improve the default in the future.

> Sorry to be a broken record but this really pushes my "feels like
> extrapolating from one example" button and such things tend to be both more
> complex and less useful than initially hoped.

Thanks for bringing this up; it's an important design guideline. In my
view, this feature carries its weight.

-Mike

Bill Pugh

unread,
Jun 9, 2008, 11:29:47 AM6/9/08
to jsr...@googlegroups.com

On Jun 6, 2008, at 11:23 PM, Michael Ernst wrote:
>
> As another example, some code is thread-safe and some is not.
> Different
> defaults might be useful there.

One point is that we aren't going to define a "default annotation"
mechanism. The mechanism I've proposed for JSR-305 only applies to
type qualifiers, not to annotations in general.

Defining a general "default annotation" is a much broader scope than
JSR-305, and would also require support at the language, JVM, and
reflection level.

Bill

Michael Ernst

unread,
Jun 10, 2008, 12:57:35 AM6/10/08
to jsr...@googlegroups.com
Bill-

> > As another example, some code is thread-safe and some is not.
> > Different
> > defaults might be useful there.
>
> One point is that we aren't going to define a "default annotation"
> mechanism. The mechanism I've proposed for JSR-305 only applies to
> type qualifiers, not to annotations in general.

Right, and given the context of the thread and my message, that's what I
was talking about.

You could define a type qualifier that says whether only typesafe
implementations of an interface, or all implementations of an interface,
are permitted to be assigned into a variable. This type qualifier was
Brian Goetz's suggestion.

-Mike

Reply all
Reply to author
Forward
0 new messages