Add nano support to Java codegen. Now the user can specify a flag nano=true
to generate naon related code in grpc service interface

Commandline example:
protoc --plugin=protoc-gen-java_rpc=build/binaries/java_pluginExecutable/java_plugin \
  --java_rpc_out=nano=true:"$OUTPUT_FILE" --javanano_out=ignore_services=true:"$OUTPUT_FILE" \
  --proto_path="$DIR_OF_PROTO_FILE" "$PROTO_FILE
diff --git a/compiler/build.gradle b/compiler/build.gradle
index 0fe03ef..6517b95 100644
--- a/compiler/build.gradle
+++ b/compiler/build.gradle
@@ -40,10 +40,17 @@
 protobufCodeGenPlugins = ["java_plugin:$buildDir/binaries/java_pluginExecutable/java_plugin"]
 
 generateTestProto.dependsOn 'java_pluginExecutable'
-test.dependsOn 'testGolden'
+test.dependsOn('testGolden','testNanoGolden')
 
 task testGolden(type: Exec, dependsOn: 'generateTestProto') {
   executable "diff"
   args "$buildDir/generated-sources/test/io/grpc/testing/integration/TestServiceGrpc.java",
        "$projectDir/src/test/golden/TestService.java.txt"
 }
+
+task testNanoGolden(type: Exec, dependsOn: 'java_pluginExecutable') {
+  environment 'TEST_TMP_DIR', temporaryDir
+  commandLine './src/test/run_nano_test.sh'
+}
+
+
diff --git a/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp
index 2947b16..b2b3894 100644
--- a/compiler/src/java_plugin/cpp/java_generator.cpp
+++ b/compiler/src/java_plugin/cpp/java_generator.cpp
@@ -60,7 +60,8 @@
 }
 
 static void PrintMethodFields(
-    const ServiceDescriptor* service, map<string, string>* vars, Printer* p) {
+    const ServiceDescriptor* service, map<string, string>* vars, Printer* p,
+    bool generate_nano) {
   for (int i = 0; i < service->method_count(); ++i) {
     const MethodDescriptor* method = service->method(i);
     (*vars)["method_name"] = method->name();
@@ -82,14 +83,43 @@
         (*vars)["method_type"] = "UNARY";
       }
     }
-    p->Print(
-        *vars,
-        "private static final $Method$<$input_type$,\n"
-        "    $output_type$> $method_field_name$ =\n"
-        "    $Method$.create(\n"
-        "        $MethodType$.$method_type$, \"$method_name$\",\n"
-        "        $ProtoUtils$.marshaller($input_type$.PARSER),\n"
-        "        $ProtoUtils$.marshaller($output_type$.PARSER));\n");
+
+    if (generate_nano) {
+      // TODO(zsurocking): we're creating two Parsers for each method right now.
+      // We could instead create static Parsers and reuse them if some methods
+      // share the same request or response messages.
+      p->Print(
+          *vars,
+          "private static final $Method$<$input_type$,\n"
+          "    $output_type$> $method_field_name$ =\n"
+          "    $Method$.create(\n"
+          "        $MethodType$.$method_type$, \"$method_name$\",\n"
+          "        $NanoUtils$.<$input_type$>marshaller(\n"
+          "            new io.grpc.nano.Parser<$input_type$>() {\n"
+          "                @Override\n"
+          "                public $input_type$ parse("
+          "$CodedInputByteBufferNano$ input) throws IOException {\n"
+          "                    return $input_type$.parseFrom(input);\n"
+          "                }\n"
+          "        }),\n"
+          "        $NanoUtils$.<$output_type$>marshaller(\n"
+          "            new io.grpc.nano.Parser<$output_type$>() {\n"
+          "                @Override\n"
+          "                public $output_type$ parse("
+          "$CodedInputByteBufferNano$ input) throws IOException {\n"
+          "                    return $output_type$.parseFrom(input);\n"
+          "                }\n"
+          "        }));\n");
+    } else {
+      p->Print(
+          *vars,
+          "private static final $Method$<$input_type$,\n"
+          "    $output_type$> $method_field_name$ =\n"
+          "    $Method$.create(\n"
+          "        $MethodType$.$method_type$, \"$method_name$\",\n"
+          "        $ProtoUtils$.marshaller($input_type$.PARSER),\n"
+          "        $ProtoUtils$.marshaller($output_type$.PARSER));\n");
+    }
   }
   p->Print("\n");
 }
@@ -526,7 +556,8 @@
 
 static void PrintService(const ServiceDescriptor* service,
                          map<string, string>* vars,
-                         Printer* p) {
+                         Printer* p,
+                         bool generate_nano) {
   (*vars)["service_name"] = service->name();
   (*vars)["service_class_name"] = ServiceClassName(service);
   p->Print(
@@ -535,7 +566,7 @@
       "public class $service_class_name$ {\n\n");
   p->Indent();
 
-  PrintMethodFields(service, vars, p);
+  PrintMethodFields(service, vars, p, generate_nano);
 
   p->Print(
       *vars,
@@ -583,7 +614,7 @@
   p->Print("}\n");
 }
 
-void PrintImports(Printer* p) {
+void PrintImports(Printer* p, bool generate_nano) {
   p->Print(
       "import static "
       "io.grpc.stub.Calls.createMethodDescriptor;\n"
@@ -607,10 +638,14 @@
       "io.grpc.stub.ServerCalls.asyncUnaryRequestCall;\n"
       "import static "
       "io.grpc.stub.ServerCalls.asyncStreamingRequestCall;\n\n");
+  if (generate_nano) {
+    p->Print("import java.io.IOException;\n\n");
+  }
 }
 
 void GenerateService(const ServiceDescriptor* service,
-                     google::protobuf::io::ZeroCopyOutputStream* out) {
+                     google::protobuf::io::ZeroCopyOutputStream* out,
+                     bool generate_nano) {
   // All non-generated classes must be referred by fully qualified names to
   // avoid collision with generated classes.
   map<string, string> vars;
@@ -627,6 +662,7 @@
   vars["ImmutableList"] = "com.google.common.collect.ImmutableList";
   vars["MethodDescriptor"] = "io.grpc.MethodDescriptor";
   vars["ProtoUtils"] = "io.grpc.proto.ProtoUtils";
+  vars["NanoUtils"] = "io.grpc.nano.NanoUtils";
   vars["StreamObserver"] = "io.grpc.stub.StreamObserver";
   vars["Iterator"] = "java.util.Iterator";
   vars["Map"] = "java.util.Map";
@@ -635,20 +671,22 @@
   vars["Immutable"] = "javax.annotation.concurrent.Immutable";
   vars["ListenableFuture"] =
       "com.google.common.util.concurrent.ListenableFuture";
+  vars["CodedInputByteBufferNano"] = 
+      "com.google.protobuf.nano.CodedInputByteBufferNano";
 
   Printer printer(out, '$');
   string package_name = ServiceJavaPackage(service->file());
   printer.Print(
       "package $package_name$;\n\n",
       "package_name", package_name);
-  PrintImports(&printer);
+  PrintImports(&printer, generate_nano);
 
   // Package string is used to fully qualify method names.
   vars["Package"] = service->file()->package();
   if (!vars["Package"].empty()) {
     vars["Package"].append(".");
   }
-  PrintService(service, &vars, &printer);
+  PrintService(service, &vars, &printer, generate_nano);
 }
 
 string ServiceJavaPackage(const FileDescriptor* file) {
diff --git a/compiler/src/java_plugin/cpp/java_generator.h b/compiler/src/java_plugin/cpp/java_generator.h
index 1af6b32..6494192 100644
--- a/compiler/src/java_plugin/cpp/java_generator.h
+++ b/compiler/src/java_plugin/cpp/java_generator.h
@@ -47,7 +47,8 @@
 
 // Writes the generated service interface into the given ZeroCopyOutputStream
 void GenerateService(const google::protobuf::ServiceDescriptor* service,
-                     google::protobuf::io::ZeroCopyOutputStream* out);
+                     google::protobuf::io::ZeroCopyOutputStream* out,
+                     bool generate_nano);
 
 }  // namespace java_grpc_generator
 
diff --git a/compiler/src/java_plugin/cpp/java_plugin.cpp b/compiler/src/java_plugin/cpp/java_plugin.cpp
index 762cc08..41c8999 100644
--- a/compiler/src/java_plugin/cpp/java_plugin.cpp
+++ b/compiler/src/java_plugin/cpp/java_plugin.cpp
@@ -31,6 +31,16 @@
                         const string& parameter,
                         google::protobuf::compiler::GeneratorContext* context,
                         string* error) const {
+    vector<pair<string, string> > options;
+    google::protobuf::compiler::ParseGeneratorParameter(parameter, &options);
+
+    bool generate_nano = false;
+    for (int i = 0; i < options.size(); i++) {
+      if (options[i].first == "nano" && options[i].second == "true") {
+        generate_nano = true;
+      }
+    }
+
     string package_name = java_grpc_generator::ServiceJavaPackage(file);
     string package_filename = JavaPackageToDir(package_name);
     for (int i = 0; i < file->service_count(); ++i) {
@@ -39,7 +49,7 @@
           + java_grpc_generator::ServiceClassName(service) + ".java";
       std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
           context->Open(filename));
-      java_grpc_generator::GenerateService(service, output.get());
+      java_grpc_generator::GenerateService(service, output.get(), generate_nano);
     }
     return true;
   }
diff --git a/compiler/src/test/golden/TestServiceNano.java.txt b/compiler/src/test/golden/TestServiceNano.java.txt
new file mode 100644
index 0000000..18f40fd
--- /dev/null
+++ b/compiler/src/test/golden/TestServiceNano.java.txt
@@ -0,0 +1,389 @@
+package io.grpc.testing.integration;
+
+import static io.grpc.stub.Calls.createMethodDescriptor;
+import static io.grpc.stub.Calls.asyncUnaryCall;
+import static io.grpc.stub.Calls.asyncServerStreamingCall;
+import static io.grpc.stub.Calls.asyncClientStreamingCall;
+import static io.grpc.stub.Calls.duplexStreamingCall;
+import static io.grpc.stub.Calls.blockingUnaryCall;
+import static io.grpc.stub.Calls.blockingServerStreamingCall;
+import static io.grpc.stub.Calls.unaryFutureCall;
+import static io.grpc.stub.ServerCalls.createMethodDefinition;
+import static io.grpc.stub.ServerCalls.asyncUnaryRequestCall;
+import static io.grpc.stub.ServerCalls.asyncStreamingRequestCall;
+
+import java.io.IOException;
+
+@javax.annotation.Generated("by gRPC proto compiler")
+public class TestServiceGrpc {
+
+  private static final io.grpc.stub.Method<io.grpc.testing.integration.Test.SimpleRequest,
+      io.grpc.testing.integration.Test.SimpleResponse> METHOD_UNARY_CALL =
+      io.grpc.stub.Method.create(
+          io.grpc.MethodType.UNARY, "UnaryCall",
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.SimpleRequest>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.SimpleRequest>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.SimpleRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.SimpleRequest.parseFrom(input);
+                  }
+          }),
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.SimpleResponse>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.SimpleResponse>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.SimpleResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.SimpleResponse.parseFrom(input);
+                  }
+          }));
+  private static final io.grpc.stub.Method<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+      io.grpc.testing.integration.Test.StreamingOutputCallResponse> METHOD_STREAMING_OUTPUT_CALL =
+      io.grpc.stub.Method.create(
+          io.grpc.MethodType.SERVER_STREAMING, "StreamingOutputCall",
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingOutputCallRequest>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingOutputCallRequest>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingOutputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingOutputCallRequest.parseFrom(input);
+                  }
+          }),
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingOutputCallResponse>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingOutputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingOutputCallResponse.parseFrom(input);
+                  }
+          }));
+  private static final io.grpc.stub.Method<io.grpc.testing.integration.Test.StreamingInputCallRequest,
+      io.grpc.testing.integration.Test.StreamingInputCallResponse> METHOD_STREAMING_INPUT_CALL =
+      io.grpc.stub.Method.create(
+          io.grpc.MethodType.CLIENT_STREAMING, "StreamingInputCall",
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingInputCallRequest>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingInputCallRequest>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingInputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingInputCallRequest.parseFrom(input);
+                  }
+          }),
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingInputCallResponse>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingInputCallResponse>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingInputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingInputCallResponse.parseFrom(input);
+                  }
+          }));
+  private static final io.grpc.stub.Method<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+      io.grpc.testing.integration.Test.StreamingOutputCallResponse> METHOD_FULL_DUPLEX_CALL =
+      io.grpc.stub.Method.create(
+          io.grpc.MethodType.DUPLEX_STREAMING, "FullDuplexCall",
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingOutputCallRequest>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingOutputCallRequest>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingOutputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingOutputCallRequest.parseFrom(input);
+                  }
+          }),
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingOutputCallResponse>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingOutputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingOutputCallResponse.parseFrom(input);
+                  }
+          }));
+  private static final io.grpc.stub.Method<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+      io.grpc.testing.integration.Test.StreamingOutputCallResponse> METHOD_HALF_DUPLEX_CALL =
+      io.grpc.stub.Method.create(
+          io.grpc.MethodType.DUPLEX_STREAMING, "HalfDuplexCall",
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingOutputCallRequest>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingOutputCallRequest>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingOutputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingOutputCallRequest.parseFrom(input);
+                  }
+          }),
+          io.grpc.nano.NanoUtils.<io.grpc.testing.integration.Test.StreamingOutputCallResponse>marshaller(
+              new io.grpc.nano.Parser<io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
+                  @Override
+                  public io.grpc.testing.integration.Test.StreamingOutputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+                      return io.grpc.testing.integration.Test.StreamingOutputCallResponse.parseFrom(input);
+                  }
+          }));
+
+  public static TestServiceStub newStub(io.grpc.Channel channel) {
+    return new TestServiceStub(channel, CONFIG);
+  }
+
+  public static TestServiceBlockingStub newBlockingStub(
+      io.grpc.Channel channel) {
+    return new TestServiceBlockingStub(channel, CONFIG);
+  }
+
+  public static TestServiceFutureStub newFutureStub(
+      io.grpc.Channel channel) {
+    return new TestServiceFutureStub(channel, CONFIG);
+  }
+
+  public static final TestServiceServiceDescriptor CONFIG =
+      new TestServiceServiceDescriptor();
+
+  @javax.annotation.concurrent.Immutable
+  public static class TestServiceServiceDescriptor extends
+      io.grpc.stub.AbstractServiceDescriptor<TestServiceServiceDescriptor> {
+    public final io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.SimpleRequest,
+        io.grpc.testing.integration.Test.SimpleResponse> unaryCall;
+    public final io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+        io.grpc.testing.integration.Test.StreamingOutputCallResponse> streamingOutputCall;
+    public final io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingInputCallRequest,
+        io.grpc.testing.integration.Test.StreamingInputCallResponse> streamingInputCall;
+    public final io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+        io.grpc.testing.integration.Test.StreamingOutputCallResponse> fullDuplexCall;
+    public final io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+        io.grpc.testing.integration.Test.StreamingOutputCallResponse> halfDuplexCall;
+
+    private TestServiceServiceDescriptor() {
+      unaryCall = createMethodDescriptor(
+          "grpc.testing.TestService", METHOD_UNARY_CALL);
+      streamingOutputCall = createMethodDescriptor(
+          "grpc.testing.TestService", METHOD_STREAMING_OUTPUT_CALL);
+      streamingInputCall = createMethodDescriptor(
+          "grpc.testing.TestService", METHOD_STREAMING_INPUT_CALL);
+      fullDuplexCall = createMethodDescriptor(
+          "grpc.testing.TestService", METHOD_FULL_DUPLEX_CALL);
+      halfDuplexCall = createMethodDescriptor(
+          "grpc.testing.TestService", METHOD_HALF_DUPLEX_CALL);
+    }
+
+    private TestServiceServiceDescriptor(
+        java.util.Map<java.lang.String, io.grpc.MethodDescriptor<?, ?>> methodMap) {
+      unaryCall = (io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.SimpleRequest,
+          io.grpc.testing.integration.Test.SimpleResponse>) methodMap.get(
+          CONFIG.unaryCall.getName());
+      streamingOutputCall = (io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+          io.grpc.testing.integration.Test.StreamingOutputCallResponse>) methodMap.get(
+          CONFIG.streamingOutputCall.getName());
+      streamingInputCall = (io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingInputCallRequest,
+          io.grpc.testing.integration.Test.StreamingInputCallResponse>) methodMap.get(
+          CONFIG.streamingInputCall.getName());
+      fullDuplexCall = (io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+          io.grpc.testing.integration.Test.StreamingOutputCallResponse>) methodMap.get(
+          CONFIG.fullDuplexCall.getName());
+      halfDuplexCall = (io.grpc.MethodDescriptor<io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+          io.grpc.testing.integration.Test.StreamingOutputCallResponse>) methodMap.get(
+          CONFIG.halfDuplexCall.getName());
+    }
+
+    @java.lang.Override
+    protected TestServiceServiceDescriptor build(
+        java.util.Map<java.lang.String, io.grpc.MethodDescriptor<?, ?>> methodMap) {
+      return new TestServiceServiceDescriptor(methodMap);
+    }
+
+    @java.lang.Override
+    public com.google.common.collect.ImmutableList<io.grpc.MethodDescriptor<?, ?>> methods() {
+      return com.google.common.collect.ImmutableList.<io.grpc.MethodDescriptor<?, ?>>of(
+          unaryCall,
+          streamingOutputCall,
+          streamingInputCall,
+          fullDuplexCall,
+          halfDuplexCall);
+    }
+  }
+
+  public static interface TestService {
+
+    public void unaryCall(io.grpc.testing.integration.Test.SimpleRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse> responseObserver);
+
+    public void streamingOutputCall(io.grpc.testing.integration.Test.StreamingOutputCallRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver);
+
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallRequest> streamingInputCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse> responseObserver);
+
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> fullDuplexCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver);
+
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> halfDuplexCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver);
+  }
+
+  public static interface TestServiceBlockingClient {
+
+    public io.grpc.testing.integration.Test.SimpleResponse unaryCall(io.grpc.testing.integration.Test.SimpleRequest request);
+
+    public java.util.Iterator<io.grpc.testing.integration.Test.StreamingOutputCallResponse> streamingOutputCall(
+        io.grpc.testing.integration.Test.StreamingOutputCallRequest request);
+  }
+
+  public static interface TestServiceFutureClient {
+
+    public com.google.common.util.concurrent.ListenableFuture<io.grpc.testing.integration.Test.SimpleResponse> unaryCall(
+        io.grpc.testing.integration.Test.SimpleRequest request);
+  }
+
+  public static class TestServiceStub extends
+      io.grpc.stub.AbstractStub<TestServiceStub, TestServiceServiceDescriptor>
+      implements TestService {
+    private TestServiceStub(io.grpc.Channel channel,
+        TestServiceServiceDescriptor config) {
+      super(channel, config);
+    }
+
+    @java.lang.Override
+    protected TestServiceStub build(io.grpc.Channel channel,
+        TestServiceServiceDescriptor config) {
+      return new TestServiceStub(channel, config);
+    }
+
+    @java.lang.Override
+    public void unaryCall(io.grpc.testing.integration.Test.SimpleRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse> responseObserver) {
+      asyncUnaryCall(
+          channel.newCall(config.unaryCall), request, responseObserver);
+    }
+
+    @java.lang.Override
+    public void streamingOutputCall(io.grpc.testing.integration.Test.StreamingOutputCallRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      asyncServerStreamingCall(
+          channel.newCall(config.streamingOutputCall), request, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallRequest> streamingInputCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse> responseObserver) {
+      return asyncClientStreamingCall(
+          channel.newCall(config.streamingInputCall), responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> fullDuplexCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      return duplexStreamingCall(
+          channel.newCall(config.fullDuplexCall), responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> halfDuplexCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      return duplexStreamingCall(
+          channel.newCall(config.halfDuplexCall), responseObserver);
+    }
+  }
+
+  public static class TestServiceBlockingStub extends
+      io.grpc.stub.AbstractStub<TestServiceBlockingStub, TestServiceServiceDescriptor>
+      implements TestServiceBlockingClient {
+    private TestServiceBlockingStub(io.grpc.Channel channel,
+        TestServiceServiceDescriptor config) {
+      super(channel, config);
+    }
+
+    @java.lang.Override
+    protected TestServiceBlockingStub build(io.grpc.Channel channel,
+        TestServiceServiceDescriptor config) {
+      return new TestServiceBlockingStub(channel, config);
+    }
+
+    @java.lang.Override
+    public io.grpc.testing.integration.Test.SimpleResponse unaryCall(io.grpc.testing.integration.Test.SimpleRequest request) {
+      return blockingUnaryCall(
+          channel.newCall(config.unaryCall), request);
+    }
+
+    @java.lang.Override
+    public java.util.Iterator<io.grpc.testing.integration.Test.StreamingOutputCallResponse> streamingOutputCall(
+        io.grpc.testing.integration.Test.StreamingOutputCallRequest request) {
+      return blockingServerStreamingCall(
+          channel.newCall(config.streamingOutputCall), request);
+    }
+  }
+
+  public static class TestServiceFutureStub extends
+      io.grpc.stub.AbstractStub<TestServiceFutureStub, TestServiceServiceDescriptor>
+      implements TestServiceFutureClient {
+    private TestServiceFutureStub(io.grpc.Channel channel,
+        TestServiceServiceDescriptor config) {
+      super(channel, config);
+    }
+
+    @java.lang.Override
+    protected TestServiceFutureStub build(io.grpc.Channel channel,
+        TestServiceServiceDescriptor config) {
+      return new TestServiceFutureStub(channel, config);
+    }
+
+    @java.lang.Override
+    public com.google.common.util.concurrent.ListenableFuture<io.grpc.testing.integration.Test.SimpleResponse> unaryCall(
+        io.grpc.testing.integration.Test.SimpleRequest request) {
+      return unaryFutureCall(
+          channel.newCall(config.unaryCall), request);
+    }
+  }
+
+  public static io.grpc.ServerServiceDefinition bindService(
+      final TestService serviceImpl) {
+    return io.grpc.ServerServiceDefinition.builder("grpc.testing.TestService")
+      .addMethod(createMethodDefinition(
+          METHOD_UNARY_CALL,
+          asyncUnaryRequestCall(
+            new io.grpc.stub.ServerCalls.UnaryRequestMethod<
+                io.grpc.testing.integration.Test.SimpleRequest,
+                io.grpc.testing.integration.Test.SimpleResponse>() {
+              @java.lang.Override
+              public void invoke(
+                  io.grpc.testing.integration.Test.SimpleRequest request,
+                  io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse> responseObserver) {
+                serviceImpl.unaryCall(request, responseObserver);
+              }
+            })))
+      .addMethod(createMethodDefinition(
+          METHOD_STREAMING_OUTPUT_CALL,
+          asyncUnaryRequestCall(
+            new io.grpc.stub.ServerCalls.UnaryRequestMethod<
+                io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+                io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
+              @java.lang.Override
+              public void invoke(
+                  io.grpc.testing.integration.Test.StreamingOutputCallRequest request,
+                  io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+                serviceImpl.streamingOutputCall(request, responseObserver);
+              }
+            })))
+      .addMethod(createMethodDefinition(
+          METHOD_STREAMING_INPUT_CALL,
+          asyncStreamingRequestCall(
+            new io.grpc.stub.ServerCalls.StreamingRequestMethod<
+                io.grpc.testing.integration.Test.StreamingInputCallRequest,
+                io.grpc.testing.integration.Test.StreamingInputCallResponse>() {
+              @java.lang.Override
+              public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallRequest> invoke(
+                  io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse> responseObserver) {
+                return serviceImpl.streamingInputCall(responseObserver);
+              }
+            })))
+      .addMethod(createMethodDefinition(
+          METHOD_FULL_DUPLEX_CALL,
+          asyncStreamingRequestCall(
+            new io.grpc.stub.ServerCalls.StreamingRequestMethod<
+                io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+                io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
+              @java.lang.Override
+              public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> invoke(
+                  io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+                return serviceImpl.fullDuplexCall(responseObserver);
+              }
+            })))
+      .addMethod(createMethodDefinition(
+          METHOD_HALF_DUPLEX_CALL,
+          asyncStreamingRequestCall(
+            new io.grpc.stub.ServerCalls.StreamingRequestMethod<
+                io.grpc.testing.integration.Test.StreamingOutputCallRequest,
+                io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
+              @java.lang.Override
+              public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> invoke(
+                  io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+                return serviceImpl.halfDuplexCall(responseObserver);
+              }
+            }))).build();
+  }
+}
diff --git a/compiler/src/test/run_nano_test.sh b/compiler/src/test/run_nano_test.sh
new file mode 100755
index 0000000..c86243a
--- /dev/null
+++ b/compiler/src/test/run_nano_test.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ -z "$TEST_TMP_DIR" ]; then
+  echo '$TEST_TMP_DIR not set'
+  exit 1;
+fi
+
+cd $(dirname $0)
+
+INPUT_FILE="proto/test.proto"
+OUTPUT_FILE="$TEST_TMP_DIR/TestServiceGrpc.src.jar"
+GRPC_FILE="$TEST_TMP_DIR/io/grpc/testing/integration/TestServiceGrpc.java"
+GOLDEN_FILE="golden/TestServiceNano.java.txt"
+
+protoc --plugin=protoc-gen-java_rpc=../../build/binaries/java_pluginExecutable/java_plugin \
+  --java_rpc_out=nano=true:"$OUTPUT_FILE" "$INPUT_FILE" && \
+  unzip -o -d "$TEST_TMP_DIR" "$OUTPUT_FILE" && \
+  diff "$GRPC_FILE" "$GOLDEN_FILE" && \
+  echo "PASS"