<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6860141866593081392</id><updated>2011-09-17T08:22:41.058-04:00</updated><category term='Java Best-Practices Legacy-Systems'/><title type='text'>Greg's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gregmattes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6860141866593081392.post-506384281720145599</id><published>2009-10-14T22:13:00.012-04:00</published><updated>2011-09-17T08:06:29.096-04:00</updated><title type='text'>A Naming  Service for Overlay Networks</title><content type='html'>I earned a Master of Computer Science degree at the University of Virginia a few years back. My &lt;a href="http://gregmattes.com/naming.pdf"&gt;master's project&lt;/a&gt; was to write a secure, peer-to-peer name resolution protocol for the &lt;a href="http://www.hypercast.org"&gt;HyperCast&lt;/a&gt; overlay network system.

&lt;p&gt;There was some flux in life around the time that I finished my degree. Our daughter was born and my academic adviser left the country within a week or two after I &lt;a href="http://gregmattes.com/naming-slides.pdf"&gt;presented&lt;/a&gt; my work. All of that was followed by a job search, and, well, the report got lost in the shuffle.

&lt;p&gt;So, some four years later, I'm now posting the &lt;a href="http://gregmattes.com/naming.html"&gt;project material&lt;/a&gt; to the web. The &lt;a href="http://hypercast.cvs.sourceforge.net/hypercast/"&gt;HyperCast code&lt;/a&gt;, including my project (just search for &lt;code&gt;Greg&lt;/code&gt; in the code) is available on SourceForge. Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6860141866593081392-506384281720145599?l=gregmattes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/506384281720145599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/506384281720145599'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/2009/10/blog-post.html' title='A Naming  Service for Overlay Networks'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6860141866593081392.post-4004881358620376810</id><published>2009-10-13T09:42:00.014-04:00</published><updated>2009-12-07T12:18:25.176-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java Best-Practices Legacy-Systems'/><title type='text'>Changing "Foundational" Code with "Soft" Fixes</title><content type='html'>&lt;p&gt;Software systems often have parts that are more "foundational" than others. Lots of other parts of the system depend on these foundational portions. A base class that has many descendant types is a good example of foundational code.

&lt;p&gt;Now, in a properly architected, designed, and factored system, such foundational portions should not be a problem. Best practices will be observed; anti-patterns will be avoided. If you work in such systems: congratulations! Write books and blogs and go forth. Stop reading now. Have a nice day.

&lt;p&gt;For the rest of us: eventually, some change will be suggested for a foundational portion of the system. How can this be done? The mere suggestion will cause other developers to say that too many things are touched by the foundational portions, best not to change things.

&lt;p&gt;Others will say that the fundamental part should be improved &lt;em&gt;because&lt;/em&gt; the portion in question is so foundational. Best to build a house on a solid foundation. Surely the political debates will rage in the wake of the suggested change.

&lt;p&gt;How can the debate be steered towards best-practices and higher-quality software? Is there some middle ground between not touching the foundational code and making a radical change that could cause the already shaky system to fail in unanticipated ways?

&lt;p&gt;What if the code is improved, but not the "whole way?" Let's consider an example (I'm thinking about Java as an implementation language here, but that's just a detail): suppose that you have some base class B. B was written years ago by a programmer armed with a humanities degree and a "Learn Java in X days" book where X is far less time than you spent working on your CS degree (and even you're still not totally sure what the &lt;a href="http://stackoverflow.com/questions/106591/do-you-ever-use-the-volatile-keyword-in-java/106787#106787"&gt;volatile keyword&lt;/a&gt; does).

&lt;p&gt;Class B was prolific and has on the order of 50 descendant classes. Changing the poorly written B could be disastrous.

&lt;p&gt;Suppose an issue arises with a particular field F of B. Field F is not initialized at construction time and so begins life as null. Now, B has an accessor and a mutator for F, so other parts of the code can change F. To make things interesting, our code poet skipped day three of his book in which he was instructed to validate his data. This means that the mutator has no guard clauses to ensure that changes to F occur with valid values.

&lt;p&gt;Then one fine day, suppose that the dreaded NullPointerException rears its ugly head because some calculation assumed that F is non-null, but alas, it is null. What happens next?

&lt;p&gt;The race is on to "fix the bug," and eventually some change is made in some descendant class for the particular case in which F is null - some believe that all is well again. Others know that little has been gained because F might be null in other cases.

&lt;p&gt;Then comes the suggestion, "why not simply initialize field F at B construction-time and then ensure the validity of field F by proper checks when it is changed?" Crazy Talk! Type B is too foundational! Too many things depend on it!! Who knows what will happen?!! Changing it could cause the lights to go out!!!

&lt;p&gt;How do we firm up the foundation while allaying fears? Suppose the "change" is "soft." Suppose that a parameter is added to all B constructors that accepts a value for F so that F can be properly initialized. Now recompile and look for errors. All of the B subtypes should be broken: fix them by passing null, or a valid value if you can easily find one at the construction point. Also, augment the B constructor and the F mutator with guard clauses that check for null. But here's the soft part: the guard clause don't do anything like throw an IllegalArgumentException, instead they generate a log message, or raise some system operator alarm, or send an email to some portion of the development team.

&lt;p&gt;&lt;span style="font-weight: bold;"&gt;The soft change shouldn't change the current behavior of the system&lt;/span&gt;. Those who were afraid to make the change win - because nothing really changed (ok, the time taken to write to the log, or send the email could cause some crazy timing bug. Technically, there was a change, but only a tiny one that is not likely to result in catastrophe).

&lt;p&gt;These checks allow you to study the system as it runs and determine where null values are generated. Analyze them one at a time in the child classes and refactor so that null is no longer passed. Eventually, you should work through them, and then, when the team can see that nulls are not being passed anymore, you can confidently change the guard clauses in B to be "hard" and throw an exception like IllegalArgumentException.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6860141866593081392-4004881358620376810?l=gregmattes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/4004881358620376810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/4004881358620376810'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/2009/10/changing-foundational-code-with-soft.html' title='Changing &quot;Foundational&quot; Code with &quot;Soft&quot; Fixes'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6860141866593081392.post-4544360971050946161</id><published>2009-10-07T22:03:00.004-04:00</published><updated>2009-10-07T22:53:37.833-04:00</updated><title type='text'>A Minimal Java Project Reading List</title><content type='html'>&lt;p&gt;This is my reading list for "enterprise" projects that use Java as the primary programming language. The list is short, but it has served me well.

&lt;p&gt;This "bare-bones" reading list is designed primarily for programmers who (like me) work on large-scale, "legacy" Java code-bases. The list could serve as the foundation for a more expanded list with "more advanced topics."

&lt;ul&gt;

&lt;li&gt;"Effective Java," 2nd edition, Bloch - this is the one book to have if you have only one book.

&lt;li&gt;"Java Concurrency in Practice," Goetz, et. al. this is a must have for concurrent enterprise apps.

&lt;li&gt;"The Java Programming Language," 4th ed. Refer to it often.

&lt;li&gt;(freely available) "The Java Language Spec," http://java.sun.com/docs/books/jls/ Refer to it just as often.

&lt;/ul&gt;

&lt;p&gt;That's it for the core, "must-have" Java stuff, but you'll need to understand patterns as well:

&lt;ul&gt;
&lt;li&gt;"Design Patterns," Gamma, et. al.

&lt;li&gt;"Patterns of Enterprise Application Architecture," Fowler
&lt;/ul&gt;

And let's not forget testing:

&lt;ul&gt;
&lt;li&gt;"xUnit Test Patterns," Meszaros
&lt;/ul&gt;

&lt;p&gt;Then there's the "recommended" section for Java, a little dated, but still relevant:

&lt;ul&gt;
&lt;li&gt;"Hardcore Java," Simmons


&lt;li&gt;"Better, Faster, Lighter Java," Tate &amp; Gehtland
&lt;/ul&gt;

&lt;p&gt;That's it. Happy reading!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6860141866593081392-4544360971050946161?l=gregmattes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/4544360971050946161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/4544360971050946161'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/2009/10/minimal-java-project-reading-list.html' title='A Minimal Java Project Reading List'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6860141866593081392.post-2971992406452418181</id><published>2008-10-16T16:10:00.004-04:00</published><updated>2008-11-22T19:48:43.732-05:00</updated><title type='text'>Static Analysis Resources</title><content type='html'>I compiled these links while putting together a talk for the Capital District Java Users Group (CDJDN) near Albany, NY. My presentation slides are posted on &lt;a href="http://cdjdn.com/index.cfm?sector=downloads&amp;page=list&amp;cat=Presentations"&gt;the group's website&lt;/a&gt;.

&lt;ul&gt;
    &lt;li&gt;Tools

        &lt;ul&gt;
        &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis"&gt;Wikipedia List of tools for static code analysis&lt;/a&gt;

        &lt;li&gt;Free/Open Source

            &lt;ul&gt;
            &lt;li&gt;&lt;a href="http://java-source.net/open-source/code-analyzers"&gt;Open Source Code Analyzers in Java&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://opensource.fortify.com"&gt;Fortify Software: Java Open Review Project&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://findbugs.sourceforge.net"&gt;FindBugs&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://checkstyle.sourceforge.net"&gt;Checkstyle&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://pmd.sourceforge.net"&gt;PMD&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://opensource.klocwork.com"&gt;Klocwork Insight Review&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://pmd.sourceforge.net/products.html"&gt;Products/books related to PMD&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://www.campwoodsw.com/sourcemonitor.html"&gt;SourceMonitor&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://sonar.codehaus.org"&gt;Sonar Open Source Quality Management Tool&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://kind.ucd.ie/products/opensource/ESCJava2"&gt;ESC/Java2&lt;/a&gt;
            &lt;/ul&gt;

       &lt;li&gt; Proprietary

            &lt;ul&gt;
            &lt;li&gt;&lt;a href="http://www.fortify.com"&gt;Fortify Software&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://www.klocwork.com"&gt;Klocwork&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://www.ouncelabs.com"&gt;Ounce Labs&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://www.coverity.com"&gt;Coverity&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://productivityapps.itbusinessnet.com/articles/viewarticle.jsp?id=520100"&gt;Cigital and Fortify Software Release Cigital Java Security Rulepack 1.0&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://www.cigital.com/securitypack"&gt;Cigital Java Security Rulepack, Version 1.0&lt;/a&gt;

            &lt;li&gt;&lt;a href="http://www.veracode.com"&gt;Veracode&lt;/a&gt;

           &lt;/ul&gt;
&lt;/ul&gt;
   &lt;li&gt; Java Compiler

        &lt;ul&gt;
        &lt;li&gt;&lt;a href="http://java.sun.com/javase/6/docs/jdk/api/javac/tree/index.html"&gt;Overview (Compiler Tree API)&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://javadots.blogspot.com/2007/12/12-steps-plan-for-extending-javac.html"&gt;The 12-steps plan (for extending the Javac compiler) - Java: Developing On The Streets&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://weblogs.java.net/blog/tball/archive/2006/09/hacking_javac.html"&gt;Tom Ball's Blog: Hacking javac&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/javac/index.html"&gt;JDK 6 Java Compiler (javac)-related APIs &amp; Developer Guides -- from Sun Microsystems&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://www.artima.com/lejava/articles/compiler_api.html"&gt;The Java Compiler API&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://today.java.net/pub/a/today/2008/03/06/jsr-294-superpackages.html "&gt;java.net: The Open Road: Superpackages&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://jcp.org/en/jsr/detail?id=199"&gt;The Java Community Process(SM) Program - JSRs: Java Specification Requests - detail JSR# 199&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/List_of_Java_virtual_machines"&gt;List of Java virtual machines - Wikipedia, the free encyclopedia&lt;/a&gt;
        &lt;/ul&gt;

   &lt;li&gt; Books

        &lt;ul&gt;
        &lt;li&gt;&lt;a href="http://pmdapplied.com"&gt;PMD Applied&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://www.dsic.upv.es/~sas2008"&gt;SAS 2008&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://www.amazon.com/Programming-Analysis-Addison-Wesley-Software-Security/dp/0321424778"&gt;Amazon.com: Secure Programming with Static Analysis (Addison-Wesley Software Security Series): Brian Chess, Jacob West: Books&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://www.amazon.com/Static-Analysis-Manuel-Hermenegildo/dp/3540442359"&gt;Amazon.com: Static Analysis: Manuel Hermenegildo, German Puebla: Books&lt;/a&gt;
        &lt;/ul&gt;

   &lt;li&gt; Talks, Blogs, etc.

        &lt;ul&gt;
        &lt;li&gt;&lt;a href="http://dlinsin.blogspot.com/2008/07/why-is-static-analysis-uncommon.html"&gt;my take on things: Why is Static Analysis Uncommon?&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://stackoverflow.com/users/13940/greg"&gt;Greg - Stack Overflow&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://stackoverflow.com/questions/4080/what-code-analysis-tools-do-you-use-for-your-java-projects"&gt;What code analysis tools do you use for your Java projects? - Stack Overflow&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-2007&amp;yr=2007&amp;track=5"&gt;JavaOne Technical Sessions - Improving Software Quality with Static Analysis - 2008&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2007.pdf"&gt;TS-2007.pdf (application/pdf Object)&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://today.java.net/pub/a/today/2008/09/11/jsr-305-annotations.html"&gt;java.net: The Open Road: javax.annotation&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://weblogs.java.net/blog/gsporar/archive/2006/11/talking_about_s.html"&gt;Gregg Sporar's Blog: Talking About Static Analysis&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://weblogs.java.net/blog/fabianocruz/archive/2006/10/java_static_ana_1.html"&gt;Fabiano Cruz's Blog: Java Static Analysis made easy with Apache Maven 2&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=GgK20Yv9QRk"&gt;YouTube - Using Static Analysis For Software Defect Detection&lt;/a&gt;
        &lt;/ul&gt;

   &lt;li&gt; Libraries

        &lt;ul&gt;
        &lt;li&gt;&lt;a href="http://jakarta.apache.org/bcel"&gt;BCEL&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://code.google.com/p/webgoat"&gt;webgoat&lt;/a&gt;

        &lt;li&gt;&lt;a href="https://javacc.dev.java.net"&gt;javacc: JavaCC Home&lt;/a&gt;

        &lt;li&gt;&lt;a href="http://www.antlr.org"&gt;ANTLR Parser Generator&lt;/a&gt;
        &lt;/ul&gt;
    &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6860141866593081392-2971992406452418181?l=gregmattes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/2971992406452418181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/2971992406452418181'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/2008/10/static-analysis-resources.html' title='Static Analysis Resources'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6860141866593081392.post-1113974228692357598</id><published>2008-08-01T13:29:00.007-04:00</published><updated>2008-08-02T16:13:03.367-04:00</updated><title type='text'>Compiling package-info.java over and over again...</title><content type='html'>&lt;p&gt;Java packages may have a corresponding &lt;code&gt;package-info.java&lt;/code&gt; source file. This file provides a central location for package-wide information. A Java compiler will compile the &lt;code&gt;package-info.java&lt;/code&gt; source file just like any other Java source file... sort of.

&lt;p&gt;The thing is, the &lt;code&gt;package-info.java&lt;/code&gt; source file is a special sort of source file:

&lt;ul&gt;

&lt;li&gt;Its contents typically consist of Javadoc documentation comments that describe the package. In fact, the &lt;code&gt;package-info.java&lt;/code&gt; feature replaces the legacy &lt;code&gt;package.html&lt;/code&gt; file that served the same purpose.

&lt;li&gt;Sometimes a package is annotated in its &lt;code&gt;package-info.java&lt;/code&gt; file.

&lt;li&gt;Usually, &lt;code&gt;package-info.java&lt;/code&gt; is devoid of source code proper.

&lt;/ul&gt;

&lt;p&gt;See &lt;a href="http://java.sun.com/docs/books/jls/third_edition/html/packages.html#7.4.1.1"&gt;The Java Language Specification, 3rd ed. sec 7.4.1.1 "Package Annotations"&lt;/a&gt; for more information on the intention of the &lt;code&gt;package-info.java&lt;/code&gt; feature.

&lt;p&gt;No corresponding &lt;code&gt;package-info.class&lt;/code&gt; file is produced by the compiler when a &lt;code&gt;package-info.java&lt;/code&gt; file contains only Javadoc comments. Why is this an issue? It's an issue because most build tools interpret the presence of an up-to-date &lt;code&gt;.class&lt;/code&gt; file as a reason not to compile a corresponding &lt;code&gt;.java&lt;/code&gt; file. Without a &lt;code&gt;package-info.class&lt;/code&gt;, a build system might compile &lt;code&gt;package-info.java&lt;/code&gt; every time the build is invoked regardless of whether &lt;code&gt;package-info.java&lt;/code&gt; has changed. Such unnecessary compiler invocations have the effect of increasing build execution time. This is not such a big deal for small projects, but the impact on build time can become annoying as the size of a codebase grows.

&lt;p&gt;In my environment a corresponding &lt;code&gt;package-info.class&lt;/code&gt; file is created only if at least one package annotation exists. Intuitively, it would seem that such annotations would need to have retention policy "stronger" than &lt;code&gt;java.lang.annotation.RetentionPolicy.SOURCE&lt;/code&gt;. However, I observe the generation of a &lt;code&gt;package-info.class&lt;/code&gt; file even if no annotation exists with a stronger retention policy (&lt;code&gt;RetentionPolicy.CLASS&lt;/code&gt; (the default) or &lt;code&gt;RetentionPolicy.RUNTIME&lt;/code&gt;).

&lt;p&gt;The presence of source code proper does not cause a &lt;code&gt;package-info.class&lt;/code&gt; file to be produced. Rather, class files with a names appropriate to the types defined in the source code are generated. For example, if I write a package private &lt;code&gt;Foo&lt;/code&gt; class in &lt;code&gt;package-info.java&lt;/code&gt;, then &lt;code&gt;Foo.class&lt;/code&gt; is generated.

&lt;p&gt;So then, how can a build be protected from unnecessarily invoking the compiler due to the lack of a &lt;code&gt;package-info.class&lt;/code&gt; file? One solution to this issue is to annotate each package with an annotation that serves no purpose other than to force the generation of a corresponding &lt;code&gt;package-info.class&lt;/code&gt; file.

&lt;p&gt;The annotation I wrote for this solution is called &lt;code&gt;ForcePackageByteCode&lt;/code&gt;. I gave it a retention policy of &lt;code&gt;RetentionPolicy.CLASS&lt;/code&gt; which clearly states that it needs to be in a &lt;code&gt;.class&lt;/code&gt; file. Just annotate the package statement in a &lt;code&gt;package-info.java&lt;/code&gt; file with &lt;code&gt;ForcePackageByteCode&lt;/code&gt;:

&lt;center&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;
/**
 * This package handles all of the foo.
 */
@ForcePackageByteCode
package com.example.foo;
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/center&gt;

&lt;p&gt;Admittedly, this solution is not ideal because it creates extraneous output for the sole purpose of optimizing future build invocations. On the plus side, the size of the extraneous files is relatively small. This minor cost in size can be well worth the build time savings over the course of a project.

&lt;p&gt;It would be nice if release candidate builds could "turn-off" the extraneous file generation by simply changing the &lt;code&gt;ForcePackageByteCode&lt;/code&gt; retention policy to &lt;code&gt;RetentionPolicy.SOURCE&lt;/code&gt;. Instead, a global search and replace opertion that changes all occurrences of the annotation to a comment for all &lt;code&gt;package-info.java&lt;/code&gt; files will do the trick:

&lt;center&gt;&lt;code&gt;@ForcePackageByteCode&lt;/code&gt; &amp;rarr; &lt;code&gt;//@ForcePackageByteCode&lt;/code&gt;.&lt;/center&gt;

&lt;p&gt;There are other solutions to this problem. The Apache Ant build tool is &lt;a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43114"&gt;addressing this issue&lt;/a&gt; with built-in tool support. The Ant team has devised some heuristics for deciding when to ignore &lt;code&gt;package-info.java&lt;/code&gt; files during compilation. Such work is helpful, but relying on support from a particular build tool has the drawback of being a partial solution if source is built in several build environments.

&lt;p&gt;Alternatively, the need for a solution like the &lt;code&gt;ForcePackageByteCode&lt;/code&gt; annotation is reduced if there is another reason for a project to annotate packages. For example, the static byte code analysis tool &lt;a href="http://findbugs.sourceforge.net"&gt;FindBugs&lt;/a&gt; supports the &lt;code&gt;edu.umd.cs.findbugs.annotations.DefaultAnnotation&lt;/code&gt; annotation. This annotation declares that specified annotations be applied to all classes, fields, and methods of a package. For example, annotating a package with &lt;code&gt;@DefaultAnnotation(NonNull.class)&lt;/code&gt; tells FindBugs that the &lt;code&gt;NonNull&lt;/code&gt; annotation should be applied to all classes, fields, and methods of a package. Applying &lt;code&gt;DefaultAnnotation&lt;/code&gt; to a &lt;code&gt;package-info.java&lt;/code&gt; file causes a &lt;code&gt;package-info.class&lt;/code&gt; to be produced obviating the need for &lt;code&gt;ForcePackageByteCode&lt;/code&gt;.

&lt;p&gt;&lt;code&gt;ForcePackageByteCode&lt;/code&gt; &lt;a href="http://virtualteamtls.svn.sourceforge.net/viewvc/virtualteamtls/trunk/utilities/src/com/iparelan/util/annotations/ForcePackageByteCode.java?view=markup"&gt;source code&lt;/a&gt; is available as part of the &lt;a href="http://virtualteamtls.sourceforge.net"&gt;Virtual Team Tools project&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6860141866593081392-1113974228692357598?l=gregmattes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/1113974228692357598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/1113974228692357598'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/2008/08/compiling-package-infojava-over-and.html' title='Compiling &lt;code&gt;package-info.java&lt;/code&gt; over and over again...'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6860141866593081392.post-504961272468075362</id><published>2008-07-31T12:32:00.007-04:00</published><updated>2008-12-18T20:13:52.978-05:00</updated><title type='text'>Java ArrayWrapperList</title><content type='html'>&lt;p&gt;I have some Java networking code that uses the Java NIO (&lt;code&gt;java.nio&lt;/code&gt;) package and the Java Concurrency utilities (&lt;code&gt;java.util.concurrent&lt;/code&gt;) package. My code is structured to enqueue pending output on a write buffer queue. The write buffer queue is a sequence of &lt;code&gt;ByteBuffer&lt;/code&gt;s implemented as a &lt;code&gt;java.util.concurrent.LinkedBlockingDeque&amp;lt;ByteBuffer&gt;&lt;/code&gt;.

&lt;p&gt;Now, I want to perform a &lt;a href="http://java.sun.com/javase/6/docs/api/java/nio/channels/SocketChannel.html#write(java.nio.ByteBuffer[],%20int,%20int)"&gt;gathering write operation&lt;/a&gt; of pending &lt;code&gt;ByteBuffer&lt;/code&gt;s in the write buffer queue. The &lt;code&gt;BlockingDeque&lt;/code&gt; has a &lt;code&gt;drainTo(Collection&amp;lt;? super E&gt;)&lt;/code&gt; method that removes elements from the &lt;code&gt;Deque&lt;/code&gt; and places them in a specified &lt;code&gt;Collection&lt;/code&gt; of the appropriate type. Here's the snag: the &lt;code&gt;java.nio.channels.SocketChannel&lt;/code&gt; &lt;code&gt;write()&lt;/code&gt; method requires a &lt;code&gt;ByteBuffer[]&lt;/code&gt;, not a &lt;code&gt;Collection&amp;lt;ByteBuffer&gt;&lt;/code&gt;.

&lt;p&gt;Converting from a &lt;code&gt;Collection&amp;lt;ByteBuffer&gt;&lt;/code&gt; to a &lt;code&gt;ByteBuffer[]&lt;/code&gt; seems as simple as calling the &lt;code&gt;java.util.Arrays.asList(T...)&lt;/code&gt; method. Just wrap the target array as a &lt;code&gt;List&lt;/code&gt; then call &lt;code&gt;write()&lt;/code&gt; with the filled array:

&lt;center&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;
ByteBuffer[] writeBufferArray = new ByteBuffer[BUFFER_COUNT]; // write() needs this
List&amp;lt;ByteBuffer&gt; writeBufferList = Arrays.asList(writeBufferArray); // drainTo() needs this
int writeBufferCount = writeBufferDeque.drainTo(writeBufferList); // fills writeBufferArray?
socketChannel.write(writeBufferArray, 0, writeBufferCount);
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/center&gt;

&lt;p&gt;Unfortunately this does not work because an &lt;code&gt;UnsupportedOperationExcepion&lt;/code&gt; is raised on the call to &lt;code&gt;drainTo()&lt;/code&gt;. This happens because the &lt;code&gt;List&lt;/code&gt; produced by &lt;code&gt;Arrays.asList(T...)&lt;/code&gt; does not permit append operations. It enforces this restriction by not implementing the &lt;code&gt;java.util.AbstractList.add(int, Object)&lt;/code&gt; method.

&lt;p&gt;It would be easy enough to copy the &lt;code&gt;ByteBuffer&lt;/code&gt;s to a "temporary" &lt;code&gt;Collection&amp;lt;ByteBuffer&gt;&lt;/code&gt;, then call the &lt;code&gt;toArray()&lt;/code&gt; method, but that results in a "double copy." Each &lt;code&gt;ByteBuffer&lt;/code&gt; reference would be copied from the &lt;code&gt;BlockingDeque&lt;/code&gt; to the temporary &lt;code&gt;Collection&amp;lt;ByteBuffer&gt;&lt;/code&gt;, then copied from the temporary &lt;code&gt;Collection&amp;lt;ByteBuffer&gt;&lt;/code&gt; to the array produced by &lt;code&gt;toArray()&lt;/code&gt;.

&lt;p&gt;Avoiding the double copy means that some way must be found to write directly to a &lt;code&gt;ByteBuffer[]&lt;/code&gt; from &lt;code&gt;drainTo()&lt;/code&gt;. Since &lt;code&gt;drainTo()&lt;/code&gt; demands a &lt;code&gt;Collection&lt;/code&gt;, some alternative array wrapper must be used.

&lt;p&gt;One potential candidate is the venerable &lt;code&gt;java.util.ArrayList&lt;/code&gt;. An &lt;code&gt;ArrayList&lt;/code&gt; properly encapsulates an array by creating an internal copy of any array given to it and producing a defensive copy when &lt;code&gt;toArray()&lt;/code&gt; is invoked on it. &lt;code&gt;ArrayList&lt;/code&gt; does its job well, but it's not suited to this task because it performs copy operations to and from its own array, not a client provided array.

&lt;p&gt;My solution for a &lt;code&gt;List&lt;/code&gt; that writes-through to an externally accessible array is called &lt;code&gt;ArrayWrapperList&lt;/code&gt;. It works like this:

&lt;center&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;
ByteBuffer[] writeBufferArray = new ByteBuffer[BUFFER_COUNT];
List&amp;lt;ByteBuffer&gt; writeBufferList = new ArrayWrapperList&amp;lt;ByteBuffer&gt;();
writeBufferDeque.drainTo(writeBufferList); // writes-through directly to writeBufferArray
socketChannel.write(writeBufferArray, 0, writeBufferCount);
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/center&gt;

&lt;p&gt;Conceptually, the code behaves as though &lt;code&gt;writeBufferList.toArray(writeBufferArray)&lt;/code&gt; is invoked immediately after the call to &lt;code&gt;drainTo()&lt;/code&gt;. It should be noted that in my production version I invoke &lt;code&gt;drainTo(Collection&amp;lt;? super E&gt;, int)&lt;/code&gt; not &lt;code&gt;drainTo(Collection&amp;lt;? super E&gt;)&lt;/code&gt;. The upper bound on the drained elements ensures that the size of &lt;code&gt;writeBufferArray&lt;/code&gt; is not exceeded.

&lt;p&gt;&lt;code&gt;ArrayWrapperList&lt;/code&gt; does not encapsulate the array it manages like &lt;code&gt;java.util.ArrayList&lt;/code&gt;. Rather &lt;code&gt;ArrayWrapperList&lt;/code&gt; trades-off encapsulation for the ability to write directly to a client accessible array.

&lt;p&gt;&lt;code&gt;ArrayWrapperList&lt;/code&gt; &lt;a href="http://virtualteamtls.svn.sourceforge.net/viewvc/virtualteamtls/trunk/utilities/src/com/iparelan/util/ArrayWrapperList.java?view=markup"&gt;source code&lt;/a&gt; is available as part of the &lt;a href="http://virtualteamtls.sourceforge.net"&gt;Virtual Team Tools project&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6860141866593081392-504961272468075362?l=gregmattes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/504961272468075362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6860141866593081392/posts/default/504961272468075362'/><link rel='alternate' type='text/html' href='http://gregmattes.blogspot.com/2008/07/java-arraywrapperlist.html' title='Java ArrayWrapperList'/><author><name>Greg Mattes</name><uri>http://www.blogger.com/profile/10010058121853224980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>
