title: NotSerializableException, unpredictable?
body: <pre><code>java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.lang.reflect.Constructor
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
      at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
      at javax.swing.event.EventListenerList.readObject(EventListenerList.java:272)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
      at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:498)
      at javax.swing.JComponent.readObject(JComponent.java:5478)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1685)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1341)
      at java.io.ObjectInputStream.access$300(ObjectInputStream.java:205)
      at java.io.ObjectInputStream$GetFieldImpl.readFields(ObjectInputStream.java:2126)
      at java.io.ObjectInputStream.readFields(ObjectInputStream.java:537)
      at java.awt.Container.readObject(Container.java:3712)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
      at javax.swing.event.EventListenerList.readObject(EventListenerList.java:272)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
      at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
      at projectserver.SQLHandler.listener(SQLHandler.java:156)
      at projectserver.SQLHandler.&lt;init&gt;(SQLHandler.java:27)
      at projectserver.Client.run(Client.java:82)
      at java.lang.Thread.run(Thread.java:722)
  Caused by: java.io.NotSerializableException: java.lang.reflect.Constructor
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
      at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
      at javax.swing.event.EventListenerList.writeObject(EventListenerList.java:257)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
      at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:438)
      at javax.swing.JComponent.writeObject(JComponent.java:5525)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1362)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1170)
      at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:161)
      at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1687)
      at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:478)
      at java.awt.Container.writeObject(Container.java:3681)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
      at javax.swing.event.EventListenerList.writeObject(EventListenerList.java:257)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
      at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
      at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
      at projectclient.ConnectionPane.sendToServer(ConnectionPane.java:131)
      at projectclient.AddRecordFrame.btnAddRecordActionPerformed(AddRecordFrame.java:144)
      at projectclient.AddRecordFrame.access$000(AddRecordFrame.java:20)
      at projectclient.AddRecordFrame$2.actionPerformed(AddRecordFrame.java:94)
      at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
      at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
      at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
      at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
      at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
      at java.awt.Component.processMouseEvent(Component.java:6504)
      at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
      at java.awt.Component.processEvent(Component.java:6269)
      at java.awt.Container.processEvent(Container.java:2229)
      at java.awt.Component.dispatchEventImpl(Component.java:4860)
      at java.awt.Container.dispatchEventImpl(Container.java:2287)
      at java.awt.Component.dispatchEvent(Component.java:4686)
      at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
      at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
      at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
      at java.awt.Container.dispatchEventImpl(Container.java:2273)
      at java.awt.Window.dispatchEventImpl(Window.java:2713)
      at java.awt.Component.dispatchEvent(Component.java:4686)
      at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
      at java.awt.EventQueue.access$000(EventQueue.java:101)
      at java.awt.EventQueue$3.run(EventQueue.java:666)
      at java.awt.EventQueue$3.run(EventQueue.java:664)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
      at java.awt.EventQueue$4.run(EventQueue.java:680)
      at java.awt.EventQueue$4.run(EventQueue.java:678)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
      at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
      at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
  </code></pre>
  
  <p>I'm not sure what code you need, so comment and I'll post. I can't reproduce this problem all the time, but sometimes it goes away after a reboot and other times it doesn't. I really don't know what's causing it. Is there something in <code>AbstractTableModel</code> that isn't serializable? I have checked that I have no nulls in my table, and there are no static members in the <code>SQLTableModel</code> class:</p>
  
  <pre><code>package projectcommon;
  
  import java.io.Serializable;
  import java.util.ArrayList;
  import javax.swing.table.AbstractTableModel;
  
  /**
   * This class is used by both the server and client, and it defines how the data
   * from the database is organised and stored. Because it is serializable it
   * provides an easy means of communicating data with the server.
   *
   * @author Logan Dam
   */
  public class SQLTableModel extends AbstractTableModel implements Serializable {
  
      /**
       * The variable used to store the table's column names.
       */
      String[] colNames;
      /**
       * The variable used to store the table's data.
       */
      ArrayList&lt;Object[]&gt; data;
      /**
       * An array defining the datatypes for the columns in the table.
       */
      Class&lt;?&gt;[] types;
      /**
       * A variable defining whether the user using the table is an admin or not.
       */
      private boolean isAdmin;
      /**
       * An array defining which columns in the table are editable.
       */
      private boolean[] isEditable;
      /**
       * A boolean variable that dictates whether the table is editable or not.
       * This is only used in special cases, such as when adding a new record to
       * the database.
       */
      private boolean addFrame = false;
  
      /**
       * Initialises a new {@code SQLTableModel} object based on predetermined data.
       *
       * @param colNames A {@code String} array containing the table's column names
       * @param types A {@code Class} array containing the table's data types.
       * @param data An {@code ArrayList} object containing the table's data.
       * @param isAdmin A {@code boolean} dictating whether the user is an admin or not.
       * @param isEditable A {@code boolean} array that defines which columns are editable
       * in the table.
       */
      public SQLTableModel(String colNames[], Class&lt;?&gt;[] types, ArrayList&lt;Object[]&gt; data, boolean isAdmin, boolean[] isEditable) {
      this.colNames = colNames;
      this.types = types;
      this.data = data;
      this.isAdmin = isAdmin;
      this.isEditable = isEditable;
  
      }
  
      /**
       * Get the data type of the given column.
       * @param columnIndex the index of the column.
       * @return A {@code Class} object representing the given column's type.
       */
      @Override
      public Class&lt;?&gt; getColumnClass(int columnIndex) {
  //  System.out.println("columnindex " + columnIndex + ": " + types[columnIndex]);
      return types[columnIndex];
      }
      /**
       * Get a column's name by index.
       * @param column the index of the column.
       * @return A {@code String} object containing the column's name.
       */
      @Override
      public String getColumnName(int column) {
      return colNames[column];
      }
      /**
       * Gets all the column names in the table.
       * @return a {@code String} array containing all the column names in the table. 
       */
  
      public String[] getColumnNames() {
      return this.colNames;
      }
  
      /**
       * Get the data contained at the specified cell.
       * @param rowIndex the row the cell lies in.
       * @param columnIndex the column the cell lies in.
       * @return an {@code Object} containing the data in the specified cell.
       */
  
      @Override
      public Object getValueAt(int rowIndex, int columnIndex) {
  //  System.out.println("rowindex: " + rowIndex);
  //  System.out.println("columnIndex: " + columnIndex);
  //  System.out.println("column length: "+ colNames.length);
  //  System.out.println("num rows: "+ + data.size());
  //
  //  for (int i = 0; i &lt; colNames.length; i++) {
  //      System.out.println("Column " + i + ": "+ colNames[i]);
  //      
  //  }
  //  for (int i = 0; i &lt; data.size(); i++) {
  //      System.out.println("row " + i + ": " + data.get(i));
  //      
  //  }
      return this.data.get(rowIndex)[columnIndex];
      }
  
      /**
       * Gets the number of columns in the table.
       * @return the number of columns in the table.
       */
  
      @Override
      public int getColumnCount() {
      return colNames.length;
      }
  
      /**
       * Gets the number of rows in the table.
       * @return the number of rows in the table.
       */
  
      @Override
      public int getRowCount() {
      return data.size();
      }
      /**
       * Sets the value of the specified cell.
       * @param aValue the new value to set the cell to.
       * @param rowIndex the row the cell lies in.
       * @param columnIndex the column the cell lies in.
       */
      @Override
      public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
      Object[] update = this.data.get(rowIndex);
      update[columnIndex] = aValue;
      this.data.set(rowIndex, update);
      fireTableCellUpdated(rowIndex, columnIndex);
      }
      /**
       * Gets an entire row of data.
       * @param row the index of the row to fetch.
       * @return an {@code Object} array containing the row's data.
       */
  
      public Object[] getRowData(int row) {
      return data.get(row);
      }
  
      /**
       * Gets all the data types for each column in the table.
       * @return A {@code Class} array containing the types for each column.
       */
      public Class&lt;?&gt;[] getTypes() {
      return types;
      }
      /**
       * Only used in special cases, sets whether the table is editable at all or not.
       * @param addFrame [@code boolean} defining if the table is editable.
       */
  
      public void setAddFrame(boolean addFrame) {
      this.addFrame = addFrame;
      }
  
      /**
       * Checks whether the specified cell is editable or not.
       * @param rowIndex The row the cell lies within.
       * @param columnIndex The column the cell within.
       * @return True if the cell is editable, otherwise false.
       */
      @Override
      public boolean isCellEditable(int rowIndex, int columnIndex) {
      if (addFrame) {
          if (isAdmin) {
          if (isEditable[columnIndex]) {
              //System.out.println("col " + columnIndex + " editable: true");
              return true;
          } else {
              //System.out.println("col " + columnIndex + " editable: false");
              return false;
          }
          } else {
          //System.out.println("col " + columnIndex + " editable: false");
          return false;
          }
      } else {
          return false;
      }
      }
      /**
       * Adds a row of data to the table.
       * @param data The row to be added.
       */
  
      public void add(Object[] data) {
      this.data.add(data);
      fireTableRowsInserted(this.data.size(), this.data.size());
      }
  
      /**
       * Checks if the table is empty.
       * @return true if the table is empty, otherwise false.
       */
      public boolean isDataEmpty() {
      return this.data.isEmpty();
      }
  }
  </code></pre>
  
  <p>The commented bits were used for debugging when I was creating my class, this class hasn't changed in a while so they're not really necessary any more.</p>
  
  <p>EDIT: <code>sendToServer()</code> is just there so I don't have to type out <code>flush()</code> and <code>reset()</code> every time I write something to the stream:</p>
  
  <pre><code>static void sendToServer(Object obj) throws IOException {
  out.writeObject(obj);
  out.flush();
  out.reset();
  }
  </code></pre>
  
  <p>where out is the <code>ObjectOutputStream</code> established with the server on connection.</p>
  
  <p>EDIT 2: this is where I send an instance of the SQLTableModel to the server:</p>
  
  <pre><code>    ConnectionPane.sendToServer("add");
      ConnectionPane.sendToServer(lblTableName.getText());
      ConnectionPane.sendToServer(addTable.getModel());
      String response = (String) ConnectionPane.in.readObject();
      if (response.equals("done")) {
      closeFrame();
      }
  </code></pre>
  
  <p>And this is the bit that receives it on the server side:</p>
  
  <pre><code> else if (cmd.equals("add")) {
      String tableName = (String) client.in.readObject();
      String exec = "add " + tableName + " (";
      SQLTableModel data = (SQLTableModel) client.in.readObject(); //this is where the exception is thrown
      ...
  </code></pre>
  
  <p><code>addTable</code> is an empty table with column names that the user fills information in. Once that's done they click add and that's where it sends that table model over.</p>