Я заменяю некоторые компоненты генерации кода в программе Java с помощью макросов Scala и выполняю ограничения на виртуальную машину Java по размеру сгенерированного байтового кода для отдельных методов (64 килобайта).Макросы Scala и ограничение размера метода JVM
Например, предположим, что у нас есть XML-файл большого размера, который представляет собой сопоставление целых чисел с целыми числами, которые мы хотим использовать в нашей программе. Мы хотим, чтобы избежать разбора этого файла во время выполнения, поэтому мы напишем макрос, который будет делать синтаксический разбор во время компиляции и использовать содержимое файла, чтобы создать тело нашего метода:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object BigMethod {
// For this simplified example we'll just make some data up.
val mapping = List.tabulate(7000)(i => (i, i + 1))
def lookup(i: Int): Int = macro lookup_impl
def lookup_impl(c: Context)(i: c.Expr[Int]): c.Expr[Int] = {
import c.universe._
val switch = reify(new scala.annotation.switch).tree
val cases = mapping map {
case (k, v) => CaseDef(c.literal(k).tree, EmptyTree, c.literal(v).tree)
}
c.Expr(Match(Annotated(switch, i.tree), cases))
}
}
В этом в случае, если скомпилированный метод будет находиться чуть выше предела размера, но вместо хорошей ошибки, говорящей о том, что нам дается гигантская трассировка стека с большим количеством вызовов до TreePrinter.printSeq
и им сообщается, что мы убили компилятор.
У меня есть a solution, который включает разбиение случаев на группы фиксированного размера, создание отдельного метода для каждой группы и добавление соответствия верхнего уровня, которое отправляет входное значение методу соответствующей группы. Он работает, но это неприятно, и я бы предпочел не использовать этот подход каждый раз, когда пишу макрос, где размер сгенерированного кода зависит от некоторого внешнего ресурса.
Есть ли более чистый способ решить эту проблему? Что еще более важно, есть ли способ более грамотно справиться с такой ошибкой компилятора? Мне не нравится идея того, что пользователь библиотеки получает сообщение об ошибке «Эта запись, похоже, убил компилятор», только потому, что некоторый XML-файл, обрабатываемый макросом, пересек некоторое (довольно низкое) размерное значение.
Этот вопрос был отмечен как [ «уже ответили»] (http://stackoverflow.com/q/6570343/334519), но то, что я спрашиваю, совершенно отличается от того, что спрашивают, что вопрос.Я знаю, что невозможно изменить ограничение размера метода JVM - я спрашиваю об обходных решениях и обработке ошибок в контексте новой (2.10) макроса Scala. –
Наивно попробовал -оптимизировать и 2.11 просто сидел там, размышляя. Поскольку мое время на этой земле конечно, я ctl-c'd. Может быть, мне станет очевидно, почему это должно было закончиться плохо. –
@ som-snytt: Интересно то же самое, и не знаю, что это значит. Без '-optimize', 2.11.0-M3 действительно дает разумное сообщение об ошибке, по крайней мере. –