Library / SDK
grpc/grpc-java avatar
grpc/grpc-java

grpc-java: the Java HTTP/2 RPC framework and how to wire it into Maven or Gradle

The Java gRPC implementation. HTTP/2 based RPC

12,074 stars4,011 forksJavaApache-2.0

At a glance

What is it?
grpc-java is the official Java implementation of gRPC, built on HTTP/2 and protobuf. It fits JVM services that need generated clients and servers, but the build wiring and the transport choice are where projects usually get stuck.
Who is it for?
Adopt grpc-java when both ends of a call are under your control and you want generated stubs, streaming, and a defined wire protocol rather than hand-written HTTP handlers. Do not adopt it to expose an API to browsers or arbitrary third parties, since the transport and the proto contract both assume cooperating peers.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What grpc-java is for, and who ends up using it

grpc-java is the Java implementation of gRPC, described in the repository as an RPC library and framework that is HTTP/2 based. The problem it addresses is the one you hit when a Java service has to call another service and you do not want to hand-write request serialization, connection handling, or method dispatch. You write a .proto file, the build generates Java types and a stub, and the call site looks like a local method invocation while the bytes travel over HTTP/2.

The audience is narrower than "anyone building a Java API". It is teams whose callers and callees are both known and can share a proto contract. That includes internal microservices, mobile clients talking to a backend, and services that need streaming rather than one request per connection. The supported platform statement is explicit: gRPC-Java supports Java 8 and later, and on Android, minSdkVersion 24 (Nougat) and later with Java 8 language desugaring. Older Java versions are not directly supported, though a branch remains available for fixes and releases, with Java 7 mapped to the 1.41.x branch. If your runtime is pinned below Java 8, you are outside the supported line, not at the edge of it.

The mechanism: protoc generates the contract, the transport carries it

There is no runtime schema negotiation here. The proto file is the contract, and protoc plus the grpc-java code generator turn it into Java classes and a base class or stub. The repository layout reflects that split: api/, core/, netty/, okhttp/, stub/, protobuf/, and compiler/ are separate modules, with compiler/ holding the code generator that ships as protoc-gen-grpc-java.

The transport is a separate dependency from the generated code, and that is the design decision worth understanding. On a non-Android JVM the README points at grpc-netty-shaded, which bundles a shaded Netty so it does not collide with a Netty version already on your classpath. On Android the README says to use grpc-okhttp instead, paired with grpc-protobuf-lite rather than grpc-protobuf. So the same proto and the same generated stubs can run over two different HTTP/2 stacks depending on where the code executes. That is convenient, but it also means a behaviour difference between platforms is a transport difference, not a codegen difference, and debugging it starts in the netty/ or okhttp/ module rather than in your service code.

Streaming is the reason many teams pick this over a JSON-over-HTTP client. Because the framing is HTTP/2, a single connection can carry multiple concurrent calls, and the generated API exposes client-streaming, server-streaming and bidirectional shapes from the same proto definitions. The cost is that you inherit HTTP/2 semantics: long-lived connections, flow control, and the need to think about what happens when a connection drops mid-stream.

Installing grpc-java with Maven or Gradle and making a first call

The README gives the dependency coordinates directly, so the first step is adding the runtime, the protobuf support, and the stub library. For Maven on a non-Android target, the three artifacts below go into pom.xml, with the Netty transport marked as runtime scope because your code compiles against the API, not the transport.

xml
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-netty-shaded</artifactId>
  <version>1.84.0</version>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-protobuf</artifactId>
  <version>1.84.0</version>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-stub</artifactId>
  <version>1.84.0</version>
</dependency>

Gradle users get the same three artifacts in a different syntax. Note that grpc-netty-shaded is runtimeOnly here as well.

gradle
runtimeOnly 'io.grpc:grpc-netty-shaded:1.84.0'
implementation 'io.grpc:grpc-protobuf:1.84.0'
implementation 'io.grpc:grpc-stub:1.84.0'

Adding the dependencies alone produces no stubs. The README says to put proto files in src/main/proto and src/test/proto along with an appropriate plugin, and then shows protobuf-maven-plugin wired with protoc and the grpc-java plugin artifact. The two configuration keys that matter are protocArtifact and pluginArtifact, because the plugin downloads a platform-specific binary using ${os.detected.classifier}, which is why os-maven-plugin appears as a build extension in the same snippet.

xml
<configuration>
  <protocArtifact>com.google.protobuf:protoc:3.25.8:exe:${os.detected.classifier}</protocArtifact>
  <pluginId>grpc-java</pluginId>
  <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.84.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>

On the Gradle side the equivalent is the com.google.protobuf plugin at version 0.9.5, with protoc.artifact and plugins.grpc.artifact set the same way, and generateProtoTasks told to apply the grpc plugin. After a build, the generated sources land under the build directory and your service extends the generated base class or uses the generated stub. The README points at the examples directory as a standalone project for a working reference, and at the quick start guide on grpc.io for a guided tour. Nothing in the README documents a rollback path if a generated-code change breaks a caller, so treat the proto file as a versioned interface from the start.

Where grpc-java is the wrong choice

The clearest limitation is reach. A gRPC endpoint is not directly consumable by a browser or by a client that cannot run generated code, so if your primary requirement is a public HTTP API that any caller can hit with curl, the generated-stub model is overhead rather than help. You would be adding a proto toolchain to produce something you then have to expose through a different surface anyway.

The build is the second place this bites. The prebuilt protoc-gen-grpc-java binary uses glibc on Linux, and the README notes that on Alpine Linux you may want the Alpine grpc-java package instead because it uses musl. That is a real constraint for container-based builds on a musl distribution: the default plugin artifact will not run, and the workaround is a distribution package rather than a Maven coordinate. Teams that build in a minimal Alpine image and copy artifacts into a Debian runtime should check which stage actually invokes protoc.

Third, the API surface is not uniformly stable. The README states that APIs annotated with @Internal are for internal use by the gRPC library and should not be used by gRPC users, and it begins a sentence about @Experimental annotations that the README excerpt leaves incomplete. The practical reading is that not everything you can reach from a dependency is a supported contract, and code that reaches into internal packages will break on upgrade. Finally, if your team has no appetite for maintaining proto files as a shared interface, the codegen step is pure cost compared with a JSON schema you can change freely.

grpc-java compared with a REST and JSON stack

The alternative most teams weigh is a REST API with JSON bodies, typically through a framework that maps annotated Java methods to HTTP routes. The difference is not speed claims, it is where the contract lives. With REST and JSON, the contract is usually prose plus whatever the handler happens to accept, and each client reimplements the mapping. With grpc-java, the contract is a .proto file compiled into both sides, so a field rename is a compile error rather than a runtime surprise.

That advantage has a matching cost. A REST endpoint can be exercised with a browser, a shell command, or any HTTP client, and it degrades gracefully when a caller sends an unexpected field. A gRPC method expects a peer that speaks the same proto revision and the same HTTP/2 framing. The repository ships an example-reflection module, which suggests server reflection is available for tooling, but the README itself does not document a curl-style workflow, so plan on tooling that understands gRPC rather than assuming your existing HTTP debugging habits transfer.

Streaming is the other axis. If your workload is request-response with occasional polling, a REST stack is simpler to operate and to reason about under partial failure. If you need a long-lived bidirectional channel, grpc-java's model is built for it and a REST stack is not, and you would be approximating it with WebSockets plus your own framing.

Maintenance, release cadence and the Apache-2.0 licence

The repository is not archived, and the last push was on 2026-09-17, four days before the date used for this review. Recent releases include v1.84.0 on 2026-09-02, v1.82.4 on 2026-08-14, and v1.82.3 on 2026-07-30. The pattern is a steady stream of patch releases on the 1.82 line alongside a newer minor, which is what you want to see if you pin a version: security and correctness fixes keep arriving on the branch you are already on.

Upgrade cost is dominated by the version string, not by API churn, because the artifacts are versioned together. The README's own snippets use 1.84.0 for grpc-netty-shaded, grpc-protobuf, grpc-stub and protoc-gen-grpc-java, and mixing versions across those four is the mistake to avoid. The protoc version is tracked separately (3.25.8 in the README examples), so a protobuf upgrade and a grpc-java upgrade are two decisions, not one.

Licensing is Apache-2.0, which is permissive and generally compatible with commercial use. The repository carries a NOTICE.txt alongside LICENSE, and Apache-2.0 obligations around attribution and notice propagation apply to redistributed binaries. That is a statement about what the repository contains, not legal advice; if you ship a shaded or repackaged artifact, have your own counsel read the NOTICE file rather than assuming the permissive label covers every distribution shape.

Editorial conclusion

Adopt grpc-java when both ends of a call are under your control and you want generated stubs, streaming, and a defined wire protocol rather than hand-written HTTP handlers. Do not adopt it to expose an API to browsers or arbitrary third parties, since the transport and the proto contract both assume cooperating peers. Before committing, verify the Java version your build targets, decide between grpc-netty-shaded and grpc-okhttp, and confirm that protoc-gen-grpc-java resolves for your operating system and libc.

Frequently asked questions

What is grpc-java?

It is the Java implementation of gRPC, described in the repository as an RPC library and framework that is HTTP/2 based. It supports Java 8 and later, and on Android minSdkVersion 24 with Java 8 language desugaring.

Why would you use gRPC instead of a REST API?

The contract lives in a .proto file that is compiled into both client and server, so an incompatible change surfaces at build time rather than at runtime. The HTTP/2 transport also carries multiple concurrent calls and streaming shapes over one connection, which a request-per-call REST stack does not model directly.

Is gRPC better than REST?

Neither is better in general. grpc-java requires a peer that speaks the same proto revision and HTTP/2 framing, so it does not suit public endpoints that arbitrary clients must call. A REST and JSON stack is simpler when the workload is request-response and callers are not under your control.

What does the G stand for in gRPC?

The README does not expand the name. It only presents the project as gRPC-Java, an RPC library and framework, and links to grpc.io for documentation.

What does gRPC stand for?

The README does not spell out the name. It identifies the project as gRPC-Java, an RPC library and framework that is HTTP/2 based, and points to grpc.io for the wider documentation.

Official sources

  1. grpc/grpc-java on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/grpc-grpc-java.svg)](https://hysenlabs.com/projects/grpc-grpc-java)