Index: lucene/contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingCodec.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingCodec.java	(revision 1197823)
+++ lucene/contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingCodec.java	(working copy)
@@ -37,7 +37,7 @@
  * compound file format.</p>
  * @lucene.experimental
  */
-public class AppendingCodec extends Codec {
+public final class AppendingCodec extends Codec {
   public AppendingCodec() {
     super("Appending");
   }
Index: lucene/contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingPostingsFormat.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingPostingsFormat.java	(revision 1197823)
+++ lucene/contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingPostingsFormat.java	(working copy)
@@ -40,7 +40,7 @@
 /**
  * Appending postings impl
  */
-class AppendingPostingsFormat extends PostingsFormat {
+final class AppendingPostingsFormat extends PostingsFormat {
   public static String CODEC_NAME = "Appending";
   
   public AppendingPostingsFormat() {
Index: lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40PostingsFormat.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40PostingsFormat.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40PostingsFormat.java	(working copy)
@@ -38,7 +38,7 @@
 // TODO: this class could be created by wrapping
 // BlockTreeTermsDict around Lucene40PostingsBaseFormat; ie
 // we should not duplicate the code from that class here:
-public class Lucene40PostingsFormat extends PostingsFormat {
+public final class Lucene40PostingsFormat extends PostingsFormat {
 
   private final int minBlockSize;
   private final int maxBlockSize;
Index: lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40Codec.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40Codec.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40Codec.java	(working copy)
@@ -53,22 +53,22 @@
   }
   
   @Override
-  public FieldsFormat fieldsFormat() {
+  public final FieldsFormat fieldsFormat() {
     return fieldsFormat;
   }
 
   @Override
-  public DocValuesFormat docValuesFormat() {
+  public final DocValuesFormat docValuesFormat() {
     return docValuesFormat;
   }
 
   @Override
-  public PostingsFormat postingsFormat() {
+  public final PostingsFormat postingsFormat() {
     return postingsFormat;
   }
   
   @Override
-  public SegmentInfosFormat segmentInfosFormat() {
+  public final SegmentInfosFormat segmentInfosFormat() {
     return infosFormat;
   }
 
Index: lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsFormat.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsFormat.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsFormat.java	(working copy)
@@ -67,7 +67,7 @@
   }
 
   @Override
-  public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
+  public final FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
     PostingsWriterBase docsWriter = wrappedPostingsBaseFormat.postingsWriterBase(state);
 
     // Terms that have <= freqCutoff number of docs are
@@ -88,7 +88,7 @@
   }
 
   @Override
-  public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
+  public final FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
 
     PostingsReaderBase docsReader = wrappedPostingsBaseFormat.postingsReaderBase(state);
     PostingsReaderBase pulsingReader = new PulsingPostingsReader(docsReader);
@@ -115,7 +115,7 @@
   }
 
   @Override
-  public void files(Directory dir, SegmentInfo segmentInfo, String segmentSuffix, Set<String> files) throws IOException {
+  public final void files(Directory dir, SegmentInfo segmentInfo, String segmentSuffix, Set<String> files) throws IOException {
     wrappedPostingsBaseFormat.files(dir, segmentInfo, segmentSuffix, files);
     BlockTreeTermsReader.files(dir, segmentInfo, segmentSuffix, files);
   }
Index: lucene/src/java/org/apache/lucene/index/codecs/simpletext/SimpleTextPostingsFormat.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/simpletext/SimpleTextPostingsFormat.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/simpletext/SimpleTextPostingsFormat.java	(working copy)
@@ -37,7 +37,7 @@
  *  any text editor, and even edit it to alter your index.
  *
  *  @lucene.experimental */
-public class SimpleTextPostingsFormat extends PostingsFormat {
+public final class SimpleTextPostingsFormat extends PostingsFormat {
   
   public SimpleTextPostingsFormat() {
     super("SimpleText");
Index: lucene/src/java/org/apache/lucene/index/codecs/PostingsFormat.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/PostingsFormat.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/PostingsFormat.java	(working copy)
@@ -18,11 +18,13 @@
  */
 
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.util.Set;
 
 import org.apache.lucene.index.SegmentInfo;
 import org.apache.lucene.index.SegmentWriteState;
 import org.apache.lucene.index.SegmentReadState;
+import org.apache.lucene.index.codecs.lucene3x.Lucene3xPostingsFormat;
 import org.apache.lucene.util.NamedSPILoader;
 
 import org.apache.lucene.store.Directory;
@@ -41,10 +43,30 @@
   
   protected PostingsFormat(String name) {
     this.name = name;
+    assert assertFinal();
   }
+  
+  private boolean assertFinal() {
+    try {
+      final Class<?> clazz = getClass();
+      if (!clazz.desiredAssertionStatus())
+        return true;
+      assert clazz.isAnonymousClass() || (this instanceof Lucene3xPostingsFormat) ||
+        (clazz.getModifiers() & (Modifier.FINAL | Modifier.PRIVATE)) != 0 ||
+        (
+          Modifier.isFinal(clazz.getMethod("fieldsConsumer", SegmentWriteState.class).getModifiers()) &&
+          Modifier.isFinal(clazz.getMethod("fieldsProducer", SegmentReadState.class).getModifiers()) &&
+          Modifier.isFinal(clazz.getMethod("files", Directory.class, SegmentInfo.class, String.class, Set.class).getModifiers())
+        ) :
+        "PostingsFormat implementation classes or at least their methods must be final";
+      return true;
+    } catch (NoSuchMethodException nsme) {
+      return false;
+    }
+  }
 
   @Override
-  public String getName() {
+  public final String getName() {
     return name;
   }
   
Index: lucene/src/java/org/apache/lucene/index/codecs/memory/MemoryPostingsFormat.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/memory/MemoryPostingsFormat.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/memory/MemoryPostingsFormat.java	(working copy)
@@ -79,7 +79,7 @@
 // TODO: Maybe name this 'Cached' or something to reflect
 // the reality that it is actually written to disk, but
 // loads itself in ram?
-public class MemoryPostingsFormat extends PostingsFormat {
+public final class MemoryPostingsFormat extends PostingsFormat {
   
   public MemoryPostingsFormat() {
     super("Memory");
Index: lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java	(working copy)
@@ -74,17 +74,17 @@
   }
   
   @Override
-  public DocValuesFormat docValuesFormat() {
+  public final DocValuesFormat docValuesFormat() {
     return docValuesFormat;
   }
 
   @Override
-  public FieldsFormat fieldsFormat() {
+  public final FieldsFormat fieldsFormat() {
     return fieldsFormat;
   }
 
   @Override
-  public SegmentInfosFormat segmentInfosFormat() {
+  public final SegmentInfosFormat segmentInfosFormat() {
     return infosFormat;
   }
 }
Index: lucene/src/java/org/apache/lucene/index/codecs/Codec.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/codecs/Codec.java	(revision 1197823)
+++ lucene/src/java/org/apache/lucene/index/codecs/Codec.java	(working copy)
@@ -18,9 +18,11 @@
  */
 
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.util.Set;
 
 import org.apache.lucene.index.SegmentInfo;
+import org.apache.lucene.index.codecs.lucene3x.Lucene3xCodec;
 import org.apache.lucene.util.NamedSPILoader;
 import org.apache.lucene.store.Directory;
 
@@ -36,14 +38,35 @@
 
   public Codec(String name) {
     this.name = name;
+    assert assertFinal();
   }
   
+  private boolean assertFinal() {
+    try {
+      final Class<?> clazz = getClass();
+      if (!clazz.desiredAssertionStatus())
+        return true;
+      assert clazz.isAnonymousClass() || (this instanceof Lucene3xCodec) ||
+        (clazz.getModifiers() & (Modifier.FINAL | Modifier.PRIVATE)) != 0 ||
+        (
+          Modifier.isFinal(clazz.getMethod("postingsFormat").getModifiers()) &&
+          Modifier.isFinal(clazz.getMethod("docValuesFormat").getModifiers()) &&
+          Modifier.isFinal(clazz.getMethod("fieldsFormat").getModifiers()) &&
+          Modifier.isFinal(clazz.getMethod("segmentInfosFormat").getModifiers())
+        ) :
+        "Codec implementation classes or at least their methods must be final";
+      return true;
+    } catch (NoSuchMethodException nsme) {
+      return false;
+    }
+  }
+  
   @Override
-  public String getName() {
+  public final String getName() {
     return name;
   }
   
-  public void files(Directory dir, SegmentInfo info, Set<String> files) throws IOException {
+  public final void files(Directory dir, SegmentInfo info, Set<String> files) throws IOException {
     postingsFormat().files(dir, info, "", files);
     //TODO: not yet fieldsFormat().files(dir, info, files);
     docValuesFormat().files(dir, info, files);
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockintblock/MockFixedIntBlockPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockintblock/MockFixedIntBlockPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockintblock/MockFixedIntBlockPostingsFormat.java	(working copy)
@@ -52,7 +52,7 @@
  * used here just writes each block as a series of vInt.
  */
 
-public class MockFixedIntBlockPostingsFormat extends PostingsFormat {
+public final class MockFixedIntBlockPostingsFormat extends PostingsFormat {
 
   private final int blockSize;
 
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockintblock/MockVariableIntBlockPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockintblock/MockVariableIntBlockPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockintblock/MockVariableIntBlockPostingsFormat.java	(working copy)
@@ -56,7 +56,7 @@
  * int is <= 3, else 2*baseBlockSize.
  */
 
-public class MockVariableIntBlockPostingsFormat extends PostingsFormat {
+public final class MockVariableIntBlockPostingsFormat extends PostingsFormat {
   private final int baseBlockSize;
   
   public MockVariableIntBlockPostingsFormat() {
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepPostingsFormat.java	(working copy)
@@ -46,7 +46,7 @@
  * This is here just to test the core sep codec
  * classes.
  */
-public class MockSepPostingsFormat extends PostingsFormat {
+public final class MockSepPostingsFormat extends PostingsFormat {
 
   public MockSepPostingsFormat() {
     super("MockSep");
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/ramonly/RAMOnlyPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/ramonly/RAMOnlyPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/ramonly/RAMOnlyPostingsFormat.java	(working copy)
@@ -59,7 +59,7 @@
  *
  *  NOTE: this codec sorts terms by reverse-unicode-order! */
 
-public class RAMOnlyPostingsFormat extends PostingsFormat {
+public final class RAMOnlyPostingsFormat extends PostingsFormat {
 
   // For fun, test that we can override how terms are
   // sorted, and basic things still work -- this comparator
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/nestedpulsing/NestedPulsingPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/nestedpulsing/NestedPulsingPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/nestedpulsing/NestedPulsingPostingsFormat.java	(working copy)
@@ -43,7 +43,7 @@
 // TODO: if we create PulsingPostingsBaseFormat then we
 // can simplify this? note: I don't like the *BaseFormat
 // hierarchy, maybe we can clean that up...
-public class NestedPulsingPostingsFormat extends PostingsFormat {
+public final class NestedPulsingPostingsFormat extends PostingsFormat {
   public NestedPulsingPostingsFormat() {
     super("NestedPulsing");
   }
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/lucene40ords/Lucene40WithOrds.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/lucene40ords/Lucene40WithOrds.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/lucene40ords/Lucene40WithOrds.java	(working copy)
@@ -42,7 +42,7 @@
 // TODO: we could make separate base class that can wrapp
 // any PostingsBaseFormat and make it ord-able...
 
-public class Lucene40WithOrds extends PostingsFormat {
+public final class Lucene40WithOrds extends PostingsFormat {
     
   public Lucene40WithOrds() {
     super("Lucene40WithOrds");
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockrandom/MockRandomPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockrandom/MockRandomPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/mockrandom/MockRandomPostingsFormat.java	(working copy)
@@ -69,7 +69,7 @@
  * Randomly combines terms index impl w/ postings impls.
  */
 
-public class MockRandomPostingsFormat extends PostingsFormat {
+public final class MockRandomPostingsFormat extends PostingsFormat {
   private final Random seedRandom;
   private final String SEED_EXT = "sd";
   
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/preflexrw/PreFlexRWCodec.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/preflexrw/PreFlexRWCodec.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/preflexrw/PreFlexRWCodec.java	(working copy)
@@ -25,7 +25,7 @@
  * Writes 3.x-like indexes (not perfect emulation yet) for testing only!
  * @lucene.experimental
  */
-public class PreFlexRWCodec extends Lucene3xCodec {
+public final class PreFlexRWCodec extends Lucene3xCodec {
   private final PostingsFormat postings = new PreFlexRWPostingsFormat();
 
   @Override
Index: lucene/src/test-framework/java/org/apache/lucene/index/codecs/preflexrw/PreFlexRWPostingsFormat.java
===================================================================
--- lucene/src/test-framework/java/org/apache/lucene/index/codecs/preflexrw/PreFlexRWPostingsFormat.java	(revision 1197823)
+++ lucene/src/test-framework/java/org/apache/lucene/index/codecs/preflexrw/PreFlexRWPostingsFormat.java	(working copy)
@@ -32,7 +32,7 @@
  *
  * @lucene.experimental
  */
-public class PreFlexRWPostingsFormat extends Lucene3xPostingsFormat {
+public final class PreFlexRWPostingsFormat extends Lucene3xPostingsFormat {
 
   public PreFlexRWPostingsFormat() {
     // NOTE: we impersonate the PreFlex codec so that it can
