Медленная компиляция с jOOQ 3.6+, простым SQL и компилятором javac
Следующая ошибка была сообщена группе пользователей jOOQ. Это действительно кажется ошибкой в компиляторе javac, связанной с довольно "сложной" работой по выводу типов, выполняемой компилятором в контексте использования внутреннего DSL, такого как jOOQ.
Учитывая общую природу ошибки, я документирую ее здесь, в Переполнении стека, для других, чтобы помочь применить обходные пути, если они столкнутся с ней. На высоком уровне это похоже на снижение производительности компилятора из-за JEP 101: Обобщенный вывод типа цели, который был представлен в Java 8 и вызывал 1-2 проблемы в прошлом.
Следующий относительно безопасный класс занимает около 20 секунд для компиляции с jdk 1.8.0_60 или 1.8.0_66 в Windows, используя Maven и jOOQ 3.7:
import static org.jooq.impl.DSL.field;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
public class Test {
public void method() {
DSL.using(SQLDialect.MYSQL)
.select()
.where(DSL.trueCondition())
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
.and(field("client.id").eq(field("client_id")))
;
}
}
pom.xml:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>compilation-issues</groupId>
<artifactId>compilation-issues</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
<version>3.7.1</version>
</dependency>
</dependencies>
</project>
Конфигурации, когда эта проблема не появляется:
- Использование jOOQ 3.5 (что-либо до 3.6.0)
- Использование jOOQ с сгенерированными классами, а не с вышеприведенным API "простого SQL"
- Использование Java 7
- Использование компилятора Eclipse
1 ответ
объяснение
В jOOQ 3.6 (когда эта проблема появляется впервые) DSL.field()
API увидел 22 новых перегрузки, принимающих разные Row
Типы в качестве аргументов:
DSL.field(Row1<T1>)
DSL.field(Row2<T1, T2>)
DSL.field(Row3<T1, T2, T3>)
- ...
Похоже, что с этим конкретным использованием API выше, новые перегрузки вызывают много проблем, когда компилятор javac пытается найти наиболее специфическую перегрузку среди всех возможных перегрузок. Следующий обходной путь компилируется мгновенно:
исправлять
Выполняется исправление для выпусков 3.9.0, 3.8.1, 3.7.4, 3.6.5, снова удаляя эти методы из общедоступного API и предоставляя переименованную замену, которая не вызывает проблем с перегрузкой.
обходные
1. Помогаем компилятору выбрать наиболее конкретный DSL.field()
перегрузка
import static org.jooq.impl.DSL.field;
import org.jooq.Field;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
public class Test {
public void method() {
Field<Object> f1 = field("client.id");
Field<Object> f2 = field("client_id");
DSL.using(SQLDialect.MYSQL)
.select()
.where(DSL.trueCondition())
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
.and(f1.eq(f2))
;
}
}
2. Предотвращение вывода целевого типа в контексте and()
метод полностью
import static org.jooq.impl.DSL.field;
import org.jooq.Condition;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
public class Test {
public void method() {
Condition condition = field("client.id").eq(field("client_id"));
DSL.using(SQLDialect.MYSQL)
.select()
.where(DSL.trueCondition())
.and(condition)
.and(condition)
.and(condition)
.and(condition)
.and(condition)
.and(condition)
.and(condition)
.and(condition)
.and(condition)
.and(condition)
;
}
}
Больше информации
Об этом ранее уже сообщалось о переполнении стека:
- Устранение неполадок при медленной компиляции
- http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8086048
И это также обсуждалось в группе пользователей jOOQ: