Skip to content

Commit e51c509

Browse files
committed
core: Rewrite class signature to avoid internal class
Leaving the class 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, the signature is used at compile time to avoid new compilations from referencing the internal-returning methods.
1 parent 43d2e53 commit e51c509

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

core/build.gradle

+50
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,47 @@ 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 bigEndian(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[], bigEndian(needle.length()), needle.getBytes(US_ASCII));
84+
byte[] replacementBytes = Bytes.concat(
85+
[1] as byte[], bigEndian(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+
project.replaceConstant(
95+
destinationDirectory.file(
96+
"io/grpc/internal/AbstractManagedChannelImplBuilder.class").get().getAsFile(),
97+
"<T:Lio/grpc/internal/AbstractManagedChannelImplBuilder<TT;>;>Lio/grpc/ManagedChannelBuilder<TT;>;",
98+
"<T:Lio/grpc/ManagedChannelBuilder<TT;>;>Lio/grpc/ManagedChannelBuilder<TT;>;");
99+
project.replaceConstant(
100+
destinationDirectory.file(
101+
"io/grpc/internal/AbstractServerImplBuilder.class").get().getAsFile(),
102+
"<T:Lio/grpc/internal/AbstractServerImplBuilder<TT;>;>Lio/grpc/ServerBuilder<TT;>;",
103+
"<T:Lio/grpc/ServerBuilder<TT;>;>Lio/grpc/ServerBuilder<TT;>;");
104+
}
105+
}
106+
57107
compileJmhJava {
58108
// This project targets Java 7 (no method references)
59109
options.errorprone.check("UnnecessaryAnonymousClass", CheckSeverity.OFF)

0 commit comments

Comments
 (0)