Skip to content

Commit dbd903c

Browse files
authored
core: Rewrite builder class signatures to avoid internal class
This provides us a path forward with #7211 (hiding AbstractManagedChannelImplBuilder and AbstractServerImplBuilder) while providing users a migration path to manage the ABI breakage (#7552). We do a .class hack so that recompiling avoids the internal class reference yet the old methods are still available. Leaving the classes as-is causes javac to compile two versions of each method, one returning the public class (e.g. ServerBuilder) and one returning the internal class (e.g., AbstractServerImplBuilder). However, we rewrite the signature that is used at compile time so that new compilations will not reference internal-returning methods. This is intended to be temporary, just to give a migration path. Once we have given users some time to recompile we will remove this rewriting and change the generics to use public classes.
1 parent ec270a7 commit dbd903c

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

core/build.gradle

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
buildscript {
2+
dependencies {
3+
classpath 'com.google.guava:guava:30.0-android'
4+
}
5+
}
6+
17
plugins {
28
id "java-library"
39
id "maven-publish"
@@ -7,6 +13,10 @@ plugins {
713
id "ru.vyarus.animalsniffer"
814
}
915

16+
import static java.nio.charset.StandardCharsets.US_ASCII;
17+
18+
import com.google.common.primitives.Bytes;
19+
1020
description = 'gRPC: Core'
1121

1222
evaluationDependsOn(project(':grpc-context').path)
@@ -53,7 +63,52 @@ animalsniffer {
5363

5464
import net.ltgt.gradle.errorprone.CheckSeverity
5565

66+
def replaceBytes(byte[] haystack, byte[] needle, byte[] replacement) {
67+
int i = Bytes.indexOf(haystack, needle);
68+
assert i != -1;
69+
byte[] result = new byte[haystack.length - needle.length + replacement.length];
70+
System.arraycopy(haystack, 0, result, 0, i);
71+
System.arraycopy(replacement, 0, result, i, replacement.length);
72+
System.arraycopy(haystack, i + needle.length, result, i + replacement.length, haystack.length - i - needle.length);
73+
return result;
74+
}
75+
76+
def bigEndianShortBytes(int value) {
77+
return [value >> 8, value & 0xFF] as byte[];
78+
}
79+
80+
def replaceConstant(File file, String needle, String replacement) {
81+
// CONSTANT_Utf8_info. https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.7
82+
byte[] needleBytes = Bytes.concat(
83+
[1] as byte[], bigEndianShortBytes(needle.length()), needle.getBytes(US_ASCII));
84+
byte[] replacementBytes = Bytes.concat(
85+
[1] as byte[], bigEndianShortBytes(replacement.length()), replacement.getBytes(US_ASCII));
86+
file.setBytes(replaceBytes(file.getBytes(), needleBytes, replacementBytes));
87+
}
88+
5689
plugins.withId("java") {
90+
compileJava {
91+
doLast {
92+
// Replace value of Signature Attribute.
93+
// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.9
94+
//
95+
// Have new compilations compile against a public class, without breaking the internal
96+
// ABI for the moment. After giving users some time to recompile, this should be removed
97+
// and #7211 can continue. When this is removed, at the very least the generics need to
98+
// be changed to avoid <? extends io.grpc.internal.*>.
99+
project.replaceConstant(
100+
destinationDirectory.file(
101+
"io/grpc/internal/AbstractManagedChannelImplBuilder.class").get().getAsFile(),
102+
"<T:Lio/grpc/internal/AbstractManagedChannelImplBuilder<TT;>;>Lio/grpc/ManagedChannelBuilder<TT;>;",
103+
"<T:Lio/grpc/ManagedChannelBuilder<TT;>;>Lio/grpc/ManagedChannelBuilder<TT;>;");
104+
project.replaceConstant(
105+
destinationDirectory.file(
106+
"io/grpc/internal/AbstractServerImplBuilder.class").get().getAsFile(),
107+
"<T:Lio/grpc/internal/AbstractServerImplBuilder<TT;>;>Lio/grpc/ServerBuilder<TT;>;",
108+
"<T:Lio/grpc/ServerBuilder<TT;>;>Lio/grpc/ServerBuilder<TT;>;");
109+
}
110+
}
111+
57112
compileJmhJava {
58113
// This project targets Java 7 (no method references)
59114
options.errorprone.check("UnnecessaryAnonymousClass", CheckSeverity.OFF)

0 commit comments

Comments
 (0)