Pull to refresh

Comments 10

Это спецификация языка Java, а речь о байткоде виртуальной машины Java. Здесь нас интересует в основном Четвёртая глава спецификации JVM. Это не единственный пример того, что можно в байткоде, но нельзя в языке Java (я вот и про вызов конструктора родительского класса написал, скажем).
Что тогда мешает создать инстанс? Не вызываем <_init_> и все.
Отличный вопрос! Если бы в спецификации не было раздела 4.10, можно было бы вытворять и не такие вещи. А так ваш класс не пройдёт верификацию и упадёт с VerifyError при загрузке класса Java-машиной. Детали можно почитать тут: 4.10.1.9.new, 4.10.1.9.invokespecial и 4.10.2.4. Вкратце это происходит так: при вызове new верификатор помещает в стек переменную специального типа uninitialized. Единственное, что с ней можно сделать — это вызвать <init>. Ну ещё можно держать в стеке и даже в локальной переменной, но попытки вызвать на ней метод, получить её поле, записать её в поле, передать в метод или вернуть из текущего метода обернутся ошибкой верификации.

Если честно, я сам не пробовал, только читал, что так нельзя делать. Попробуйте :-)
Не знаю как сейчас, раньше была еще разница в том как javac и ecj именуют вложенные анонимные классы в анонимные классы т.е
class A {
  public Runnable a(){
  return new Runnable(){
    public void run(){
      Runnable a = new Runnable(){
        public void run(){}
      }
      a.run();
    }
    }
  }
}


javac создавал классы A$1 и A$1$1, тогда как ecj A$1 и A$2
Насчёт раньше — не знаю, но сейчас одинаково именуют — A$1$1.
Плюсов у статьи почему-то немного, но хочется отметить её крайнюю информативность. Спасибо вам, автор, обязательно пишите ещё про такие вещи!
Это стандартная проблема узкоспециализированных статей, к сожалению.
Спасибо за отзыв. Рад, что кому-то пригодилось.
Sign up to leave a comment.

Articles