diff --git a/apps/sam/java/src/net/i2p/sam/SAMBridge.java b/apps/sam/java/src/net/i2p/sam/SAMBridge.java
index bc99762f1a62dba0085106d705bb3edbe9198e03..18f9cbe742ab09dc2a64a83f8f7e0e0bb2f3eecc 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMBridge.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMBridge.java
@@ -341,7 +341,7 @@ public class SAMBridge implements Runnable, ClientApp {
 
     ////// end ClientApp helpers
 
-    static class HelpRequested extends Exception {static final long serialVersionUID=0x1;}
+    private static class HelpRequestedException extends Exception {static final long serialVersionUID=0x1;}
 
     /**
      * Usage:
@@ -439,11 +439,11 @@ public class SAMBridge implements Runnable, ClientApp {
         return new Options(host, port, opts, keyfile);
     }
 
-    private static Properties parseOptions(String args[], int startArgs) throws HelpRequested {
+    private static Properties parseOptions(String args[], int startArgs) throws HelpRequestedException {
         Properties props = new Properties();
         // skip over first few options
         for (int i = startArgs; i < args.length; i++) {
-        	if (args[i].equals("-h")) throw new HelpRequested();
+        	if (args[i].equals("-h")) throw new HelpRequestedException();
             int eq = args[i].indexOf('=');
             if (eq <= 0) continue;
             if (eq >= args[i].length()-1) continue;
diff --git a/apps/sam/java/src/net/i2p/sam/SAMException.java b/apps/sam/java/src/net/i2p/sam/SAMException.java
index def5709ea58ef039f2a9ffcc6dfe2f738b1b6ba7..a2c2518821b1caeb8518976944bd167842b98df8 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMException.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMException.java
@@ -15,7 +15,7 @@ package net.i2p.sam;
  */
 class SAMException extends Exception {
 
-	static final long serialVersionUID = 1 ;
+    private static final long serialVersionUID = 1;
 
     public SAMException() {
     	super();
@@ -24,4 +24,9 @@ class SAMException extends Exception {
     public SAMException(String s) {
     	super(s);
     }
+    
+    /** @since 0.9.14 */
+    public SAMException(String s, Throwable cause) {
+        super(s, cause);
+    }
 }
diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
index 194e3c27138eb880f5ba8f6ca690352055ecda01..35d4411095756e803859d60a01959dc6cd956e66 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java
@@ -46,10 +46,9 @@ class SAMHandlerFactory {
             }
             tok = new StringTokenizer(line.trim(), " ");
         } catch (IOException e) {
-            throw new SAMException("Error reading from socket: "
-                                   + e.getMessage());
+            throw new SAMException("Error reading from socket", e);
         } catch (Exception e) {
-            throw new SAMException("Unexpected error: " + e.getMessage());
+            throw new SAMException("Unexpected error", e);
         }
 
         // Message format: HELLO VERSION MIN=v1 MAX=v2
diff --git a/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java b/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java
index 44e93f21cb4175a586c00bf8530fd964ca634a7f..498cef4b8faecf481f8fa1cb6929d9705eb0a7cb 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java
@@ -15,7 +15,7 @@ package net.i2p.sam;
  * @author human
  */
 class SAMInvalidDirectionException extends Exception {
-	static final long serialVersionUID = 1 ;
+    private static final long serialVersionUID = 1;
 	
     public SAMInvalidDirectionException() {
 	super();
diff --git a/apps/sam/java/src/net/i2p/sam/SAMUtils.java b/apps/sam/java/src/net/i2p/sam/SAMUtils.java
index 6e04cadfb570927ba5b695b1f0a52e715a04c9f6..14d9991cf451a78810cde03a09c2ff81f79278f9 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMUtils.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMUtils.java
@@ -78,10 +78,10 @@ class SAMUtils {
         }
     }
     
-    public static class InvalidDestination extends Exception {
+    public static class InvalidDestinationException extends Exception {
     	static final long serialVersionUID = 0x1 ;
     }
-    public static void checkPrivateDestination(String dest) throws InvalidDestination {
+    public static void checkPrivateDestination(String dest) throws InvalidDestinationException {
     	ByteArrayInputStream destKeyStream = new ByteArrayInputStream(Base64.decode(dest));
 
     	try {
@@ -89,7 +89,7 @@ class SAMUtils {
     		new PrivateKey().readBytes(destKeyStream);
     		new SigningPrivateKey().readBytes(destKeyStream);
     	} catch (Exception e) {
-    		throw new InvalidDestination();
+    		throw new InvalidDestinationException();
     	}
     }
 
diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java
index 85c0955f56dd10341a9de6ac3082b3c6931617b9..0370c6a2158d6a8a4d74ab936821e5d3565b0a81 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java
@@ -250,13 +250,14 @@ class SAMv3Handler extends SAMv1Handler
 
 	public static class SessionsDB
 	{
-		static final long serialVersionUID = 0x1 ;
+		private static final long serialVersionUID = 0x1;
 
-		static class ExistingId   extends Exception {
-			static final long serialVersionUID = 0x1 ;
+		static class ExistingIdException   extends Exception {
+			private static final long serialVersionUID = 0x1;
 		}
-		static class ExistingDest extends Exception {
-			static final long serialVersionUID = 0x1 ;
+
+		static class ExistingDestException extends Exception {
+			private static final long serialVersionUID = 0x1;
 		}
 		
 		private final HashMap<String, SessionRecord> map;
@@ -265,14 +266,15 @@ class SAMv3Handler extends SAMv1Handler
 			map = new HashMap<String, SessionRecord>() ;
 		}
 
-		synchronized public boolean put( String nick, SessionRecord session ) throws ExistingId, ExistingDest
+		synchronized public boolean put( String nick, SessionRecord session )
+			throws ExistingIdException, ExistingDestException
 		{
 			if ( map.containsKey(nick) ) {
-				throw new ExistingId();
+				throw new ExistingIdException();
 			}
 			for ( SessionRecord r : map.values() ) {
 				if (r.getDest().equals(session.getDest())) {
-					throw new ExistingDest();
+					throw new ExistingDestException();
 				}
 			}
 
@@ -316,7 +318,7 @@ class SAMv3Handler extends SAMv1Handler
 	
 	private boolean stolenSocket;
 	private boolean streamForwardingSocket;
-	
+
 	public void stealSocket()
 	{
 		stolenSocket = true ;
@@ -501,7 +503,7 @@ class SAMv3Handler extends SAMv1Handler
 
 				try {
 					SAMUtils.checkPrivateDestination(dest);
-				} catch ( SAMUtils.InvalidDestination e ) {
+				} catch ( SAMUtils.InvalidDestinationException e ) {
                     return writeString("SESSION STATUS RESULT=INVALID_KEY\n");
 				}
 
@@ -535,11 +537,11 @@ class SAMv3Handler extends SAMv1Handler
 
 				try {
 					sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ;
-				} catch (SessionsDB.ExistingId e) {
+				} catch (SessionsDB.ExistingIdException e) {
 					if (_log.shouldLog(Log.DEBUG))
 						_log.debug("SESSION ID parameter already in use");
 					return writeString("SESSION STATUS RESULT=DUPLICATED_ID\n");
-				} catch (SessionsDB.ExistingDest e) {
+				} catch (SessionsDB.ExistingDestException e) {
 					return writeString("SESSION STATUS RESULT=DUPLICATED_DEST\n");
 				}