Ключевое слово var

Прошедшее 8-е марта для разработчиков Java выдалось особенно насыщенным. Причиной тому послужил новый JEP 286: Local-Variable Type Inference, который предлагает ввести ключевое слово var, избавляя нас от необходимости явно указывать тип локальной переменной:

var unbufOut = NetUtils.getOutputStream(sock);

вместо

OutputStream unbufOut = NetUtils.getOutputStream(sock);

А на днях подоспели и результаты опроса разработчиков, которые недвусмысленно показали — var в Java быть. Хорошо это или плохо?

Судя по лентам Твиттера и результатам опроса, первая реакция многих разработчиков (включая меня) была такой:

No god please no

Я решил разобраться, почему этот JEP вызывает у меня отторжение.

Почему «нет»


Java всегда была и остается достаточно консервативной платформой. Иногда этот консерватизм реально ограничивает пользователей. Нашумевшая история с выпиливанием Unsafe, проникновение которого во многом есть результат игнорирования нарастающей потребности в низкоуровневом API, — ярчайший тому пример.

Консервативность языка, напротив, давала Java ряд преимуществ. Во-первых, это низкий порог вхождения. Базовый синтаксис языка очень компактен, и прост в изучении. Во-вторых, это экспрессивность. Языки, напичканные всевозможными фишечками, вроде Scala и C#, позволяют писать совершенно нечитаемые конструкции. Смешайте лямбды, type inference и имплицитный return, и читателям вашего кода придется хорошенько напрячься. В Java написать нечитаемый код значительно сложнее.

Отсюда и главная претензия к var — риск снижения читабельности. На практике мы «понимаем» код во многом благодаря трем составляющим: типы переменных, имена переменных, и имена методов. Повсеместное (а в худшем случае — бездумное) использование var, уничтожит первую из них. Для поддержания читабельности на том же уровне, придется больше внимания уделять именам методов, так как их вклад в восприятие кода значительно возрастет.


Так же важно заметить, что мейнстримовые языки программирования тесно связаны со средами разработки. По сути, мы работаем не с языком, я с экосистемой язык-IDE. Благодаря этому среда разработки может легко компенсировать какие-то недостающие Вам языковые конструкции. В современных IDE потребность в механическом написании чего-либо уже близка к нулю. Таким образом, сам язык может оставаться неизменным, в то время как IDE будет брать на себя всю грязную работу, максимально учитывая пожелания и привычки конкретного пользователя.

Люди пишут в опроснике:
Scope is small, so will only give more confussion to new developers. The typing of the boiler plate is tackled by decent IDEs.
We have IDEs so I don't care

В комплексе все это делает преимущества type inference достаточно сомнительными.

Особенно непросто придется любителям разработки «в блокноте». Существует мнение, что данный аргумент высосан из пальца, так как все пользуются IDE, а условный «notepad» — это удел фриков, неадекватных работодателей и джуниоров, пишущих свой первый «Hello, world!». Это не совсем так. IDE — это инструмент работы с кодом. Но сам код находится в других местах: в файлах, в mail-листах, в баг-трекерах, на форумах, и так далее. Когда вы открываете JIRA-тикет с куском кода, Вы сначала читаете его в браузере, верно? Поэтому чтение кода вне среды разработки — совершенно нормальная и распространенная практика, которой занимаются едва ли не все разработчики. Есть вполне обоснованные опасения, что var этот процесс затруднит.

I'm not sure if it will not increase the difficulty of code review
I code both in Java and C# and sometimes and need to work with C# code where people have used var. It makes it a lot harder to see the type of a variable for no or very little gain.

Почему «да»


Нет фич в языке — нет проблем. Такая логика имеет право на жизнь, но она ущербна. Любая инженерная деятельность — это поиск малого количества правильных решений в бесконечном множестве неправильных. Страх ошибок и некорректного использования не должен останавливать развитие языка.

Для аналогии вспомним ООП. При правильном использовании это невероятно полезный и мощный инструмент. Поэтому ООП везде. При этом код инженера, который только-только закончил читать Gang Of Four, лучше обходить стороной. Он будет чрезмерно сложным и перегруженным. И только через некоторое время, после того, как человек набьет руку в проектировании, ООП начинает давать свои плоды.

С развитием языка ситуация ровно та же. Появляется новый инструмент. Какое-то время люди учатся, притираются, делают ошибки. Появляются новые тренды и подходы, которые находят своих сторонников и противников. Наконец, образуются устоявшиеся практики, которые применяют в конкретных проектах.

Поэтому до начала массового использования var, достаточно сложно сказать, насколько много проблем и неудобств оно принесет. Но мы можем обратиться к языкам, которые уже имеют type inference — C++, C#, Scala… давайте иначе — а в каком известном вам мейнстримовом языке этого нет? Лично у меня нет информации о том, чтобы какой-то язык серьезно пострадал от type inference. Кто-то пользуется, а кто-то нет, кому-то нравится, а кому-то нет, вот и все.

Ради эксперимента я походил по кодовой базе Akkа и Spark. Намеренно искал места, в которых было бы сложно разобраться конкретно из-за type inference. Субъективно — не нашел. В подавляющем большинстве мест смысл переменной был легко понятен из контекста благодаря именам переменных и методов. По моим ощущениям, хороший код не пострадает. А вот плохой код может стать еще хуже. Ну и бог с ним.


Наконец, давайте вспомним, за что большего всего критикуют Java. Это скудные возможности языка, и монструозный энтерпрайз. В последние годы обе проблемы начали разрешаться — язык развивается, а J2EE в том виде, в котором мы его знали раньше, постепенно отмирает. Оба этих процесса позволят значительно укрепить лидерство Java среди других языков и платформ.

Мне всегда было достаточно сложно понять мотивацию больших и сложных проектов, использующих JVM-based языки. Например, что получили Akka и Spark от использования Scala? Издержки очевидны — дополнительный барьер между продуктом и миллионами Java-разработчиков. А польза? Добавление новых фич, начиная с такой важнейшей вещи, как лямбды, и заканчивая относительно бесполезным var, позволит прекратить разброд и шатания, и вновь сконцентрирует комьюнити вокруг непосредственно Java. Это безусловный плюс.

Thanks so much! This will remove yet another death-by-a-thousand-cuts issues w Java that drive people to seek alternatives
Please simplifiy the Java language (and JavaEE in general)! Type inference is a great step into the right direction.

Итог


Исключительно субъективно: с точки зрения разработчика это «никакая» фича. Пользы мало, вреда мало. Но в целом для языка это однозначный шаг вперед. Один из многих, которых мы с нетерпением ждем:
Is there way to add union and intersection types in Java?
Could you consider the introduction of case classes (like in Scala)?
when do you expect primitive types be allowed in generics?
Remove getters and setters.
When will we have async/await feature in Java ( like c# and f# ) ?

Но лично я пользоваться var не хочу. Блокнот сподручнее.

Комментарии (324)


  1. Throwable
    28.03.2016 13:44
    +2

    Вывод типов уже есть в джаве для лямбд. Логичный шаг — сделать для локальных переменных.
    Когда хорошо: когда тип переменной полностью ясен из правого выражения (new, Factory.create, присвоение поля, etc...). Когда плохо: когда тип не ясен без ползания в сторонние api (var out = manager.getOutput()), когда тип нужно привести к интерфейсу (Map<String,String> cache = new MyPersonalLocalCacheImplementation()).
    Ухудшится ли читаемость кода? Бесспорно. Однако, когда были введены лямбды, в которых встроен вывод типов, никто сильно не протестовал. Так что дело спасут умеренное использование и более выразительные названия переменных.

    P.S. опять разработчики джавы пытаются сэкономить буквы, но делают это не там. Уже давно пора ввести properties в джава и убрать весь этот уродский мусор с геттерами-сеттерами.


    1. Flammar
      28.03.2016 14:40

      Насчёт геттеров-сеттеров — подозреваю, что всё тут сильно завязано на рефлексию и её подчёркнуто ограниченное использование. Нельзя в Java делать properties просто синтаксическим сахаром.


      1. Throwable
        28.03.2016 15:20

        Как раз можно. Другие языки как Groovy, Scala, Kotlin генерируют без проблем Java-совместимые проперти. Единственное, что может дать проблемы — это JavaDoc, которому нужен исходник с геттерами-сеттерами.


    1. webkumo
      29.03.2016 11:19

      Воспользуйтесь уже ломбоком и будет вам счастье с геттерами-сеттерами. Вот только иногда всё-равно приходится переопределять геттер/сеттер, если поле в итоге не просто проперти.


  1. Flammar
    28.03.2016 14:38
    +1

    Ну в Java уже есть такая опция, которой принято не пользоваться, как объявление нескольких переменных одним оператором. Будет ещё одна...


  1. OlegTar
    30.03.2016 14:54

    Какой смысл писать

    List<int> a = new List<int>():

    Когда можно написать
    var a = new List<int>();

    Другой случай, когда пишется
    var a = function();

    Это неудобно, нужно заглядывать внутрь определения функции function, чтобы знать, что она возвращает.
    Таким образом пишите var тогда, когда и так понятно, какого типа должна быть переменная, никуда не ходя, и будет счастье.


    1. iCpu
      31.03.2016 08:00

      После плюсов это была главная вещь, которая резанула глаза (и продолжает резать) в c#\Java. Все более-менее сложные объекты приходится создавать через new, но, при этом, на коде это никак не сказывается. То есть нельзя по какому-либо участку кода сказать, нужно ли переменную проверять на null или нет. В плюсах в этом плане куда более удобный для понимания синтаксис. Как минимум, понимаешь, в каком случае переменную нужно проверять на null и уточнять её тип, освобождать память и тп, а в каком — нет. И сейчас в меня какашкой бросят за такие слова.


      1. webkumo
        31.03.2016 08:34

        Какашкой не бросим, но без примеров — пустословие какое-то получается.


        1. iCpu
          31.03.2016 09:08

          Банальщина.
          @Nullable
          List a = null;
          List b = new List():
          int c = 0;
          /*...*/
          if (a != null)
          { a.append©; }
          b.append©;

          И ни единого способа узнать посреди кода о свойствах объектов без помощи IDE либо пролистывания кода. У плюсов всё подругому.

          std::list* a = new std::list();
          std::list b;
          int c = 0;
          if (a != nullptr)
          { a->append©; }
          b.append©;

          В плюсах b сравнивать просто не имеет смысла. А для a сразу видно, что нужно следить за памятью, как минимум, помнить, кто за неё в ответе. /* Надеюсь, обойдётся без мусорных холиваров. */

          И, да, я не гарантирую правильность Java-кода. Чукча не писатель.


          1. iCpu
            31.03.2016 09:14
            +1

            Вы даже не представляете, какой осадок у меня выпал, когда я посмотрел на отхабренный комментарий… Это просто ©ча©тье какое-то!


          1. webkumo
            01.04.2016 02:42
            +1

            Я, аналогично, не писатель c++ — можете пояснить фразу «В плюсах b сравнивать просто не имеет смысла»?
            С моей точки зрения (как это в c++ я не знаю) — b объявлено, но не инициализировано (в этом случае для локальных переменных в java сломается компиляция). Помимо этого я вижу, что b вроде как объект, а не ссылка на объект (но вот тут сознание буксует, чем это нам аукается — с не менеджед языками я не работал уже бог весть сколько).


            1. OlegTar
              03.04.2016 02:49

              b объявлено, но не инициализировано

              Нет, b тут будет как раз инициализировано.

              Как я понял, iCpu имеет в виду, что b не может быть null'ом вообще, а 'a' — может (потому что это указатель).


              1. webkumo
                03.04.2016 02:55

                Ага, спасибо… Привык уже, что в java всё, кроме нативных типов, является ссылкой…


      1. ApeCoder
        31.03.2016 09:00

        На null должен проверять компилятор https://kotlinlang.org/docs/reference/null-safety.html


        1. iCpu
          31.03.2016 09:27
          -1

          Я не совсем в курсе, kotlin — это новое название Java или просто Another one bites to JVM? Я понимаю, что компилятор должен быть умным, но… Он был, есть и будет тупым. https://habrahabr.ru/post/164027/


          1. ApeCoder
            31.03.2016 09:50

            Kotlin это новый язык от jetBrains/IntelliJ — произодителя idea.


            1. iCpu
              31.03.2016 09:53
              -1

              Отлично. А причём тут Java?


              1. ApeCoder
                31.03.2016 09:57

                1) Мы обсуждаем дизайн языков, в частности у вас проскочило сравнение C++, C# и Java — я высказал мнение как это должно быть
                2) Для Java программистов имеет смысл посмотреть н Kotlin так как там не только внесли новые фишки, но и смотрят на interoperability c Джавой
                Кстати, в C# 7 тоже планировали non-nullable types но вынесли похоже из последней редакции.


                1. iCpu
                  31.03.2016 11:00

                  1) Вводятся квалификатор типа "?" и оператор "?.". Казалось бы, причём тут "*" и "->"? К тому же интересно, как компилятору проверить то, что известно только в реалтайме?
                  2) Я сейчас выскажу достаточно противоречивую точку зрения, но… Чтобы нормально «посмотреть» ЯП, нужно не один день затратить. Иногда хорошая, казалось бы, идея на деле оказывается не самой удобной. К примеру с (1), в c++ можно сделать шаблоны, которые будут внедрять все эти фичи задёшего. Но что-то никто не торопится это делать. Необходимости нет.
                  Так вот, можно бегать и смотреть, какой из ЯП наиболее сладок для тебя. А можно не бегать, а выбрать один и изменять наиболее неприятные его места. Теорема Эскобара применима.


                  1. ApeCoder
                    31.03.2016 11:04

                    1) Вы почитайте — он не проверяет, то, что известно в рантайме, он требует от вас кода проверки, если ссылка nullable а вы ее используете не проверяя.
                    2) Давайте сделайте шаблон, чтобы
                    x -> SomeMethod() требовало бы проверки а
                    if (x!=NULL)
                    {
                    x-> SomeMethod()
                    }
                    компилировалось бы
                    3) Еще можно поверх Джавы проверять статическим анализом (что и делают IDE, но вам же нужно без IDE)


                    1. iCpu
                      31.03.2016 11:43

                      1) И не даёт нормально приводить типы между nullable и non-nullable. Где же здесь подвох?
                      2) Во-первых, «можно сделать» != «ща, за 3 минуты в комментах забацаю». Во-вторых, «внедрять все эти фичи» != «внедрять фичи с полным сохранением синтаксиса». Если мы это учитываем, то почему нет? Никто не запрещал ни перегружать оператор ->, ни добавлять функторы, ни писать макросы. Самое тупое и быстрое, что я могу придумать, это
                      #define call(a,b) if (a) a->b;
                      а в бустах давным давно лежит boost::optional. Да, написать шаблон, который оборачивает возвращаемые типы всех методов, не так просто, но возможно.
                      3) Как и плюсы точить vargrind'ом или PVS-studio.


                      1. ApeCoder
                        31.03.2016 11:52

                        1) Что такое "нормально"?
                        2) В котлине есть способ так же аннотировать окружающий Java код. Посмотрим, что из жтого получится.
                        3) Дада, только в Java есть уже стандартый nonnullable атрибут, насколько я знаю, а в ,NET часть FW уже аннотирована.
                        Есть разница между теоретической возможностью сделать что-то похожее, полноценным языком и поддержкой экосистемы.


                        1. iCpu
                          31.03.2016 12:00

                          1) operator=
                          2) Я, видимо, не понимаю, чего вы здесь от меня хотите или, наоборот, чего пытаетесь впихнуть.
                          3) MyClass class; //Nonnullable since long long ago in the days when ALGOL was still in some use


                          1. ApeCoder
                            31.03.2016 14:49

                            1) Non nullable так можно привести к nullable, а наоборот только со значком "я уверен в себе и разрешаю здесь случиться эксепшену"
                            2) Я в том смысле, что если вы и изобретете свои типы на C++ то надо еще будет обучить этому самому окружающие библиотеки — в котлине этот вопрос решен.
                            3) Я не очень понял, что вы хотите этим сказать. Если что можно написать коммент, то надо еще поддержать это в инструментах. Если это означает value тип в C++, тогда проблема переезжает в ссылки.


                            1. iCpu
                              31.03.2016 20:59

                              1) То есть, указатели с принудительной проверкой. Можно взять адрес, обратное — неверно.
                              2) Если под «этот вопрос решен» вы имеете в виду «с тех пор, как это вошло в стандарт, этим все пользуются», не вижу существенных отличий. Если же смысл в «библиотеки не придётся переделывать под новый синтаксис», то… Да ладно!
                              3) Единственный смысл ссылок — передавать в функцию объект, а не значение. Все побочные использования — синтаксический сахар, окромя move-семантики.
                              Я имею в виду простую вещь — любые попытки доказать плюсовику «а у нас можно создавать объекты, которые не обращаются в null» вызывают тупую реакцию «вы что, 20 лет шли к тому, чтобы создавать объекты на стеке?» Весь этот синтаксический сахар с короткими записями условий и автоматический возврат null при любом неверном чихе не меняет простой вещи: ваш язык упёрся в указатели. Притом. создатели ввели новый синтаксис, чтобы показать — это не указатели, но это чёртовы указатели. Они ведут себя, как указатели. Они пахнут как указатели. Они на вкус как указатели. Даже выглядят как чёртовы умные указатели, ведь в JVM нет способа заглушить сборщик мусора. Так почему мне пытаются втындюрить, что это не указатели, а манна небесная, и что все IDE их будут поддерживать, в отличие от плюсовых, в которых… всё отлично поддерживается? Или вся проблема в том, что компилятор плюсов при стандартных настройках — не истеричка?


                              1. ApeCoder
                                31.03.2016 21:10

                                1) Ненене, все указатели, можно сделать два указателя на один объект и они будут не nullable оба.
                                2) Не проверял, но есть возможность добавлять внешние аннотации.
                                3) Нет это не указатели, это именно ссылки — нет никакой арифметики. И non-nullable ссылки это ссылки то же. Две non-nullable ссылки могут указывать на один и тот же объект


                                1. iCpu
                                  01.04.2016 05:25

                                  1) 3) А вы в курсе, что уже 21 век и что unique_ptr, shared_ptr и weak_ptr — это часть стандарта уже более 5 лет?
                                  2) Это, конечно, круто, но это просто ужасно. Вы понимаете, к чему ведёт размазывание определения поведения кода по большому числу разномастных файлов?


                                  1. ApeCoder
                                    01.04.2016 08:08

                                    1) Тогда при чем здесь стек? (p.s. я про 21 век не в курсе, последнюю поделку на C++ ковырял лет 10 назад да и то неидеоматично)
                                    2) Это компромисс — вы можете выбрать или самому или с сообществом поддерживать внешнее описание при этом получить поддержку nullability или забить. Для typescript сообщество поддерживает, полные описания типов для распространненных javascript библиотек, например http://definitelytyped.org/


                                    1. iCpu
                                      01.04.2016 08:27

                                      1) Технические подробности реализации. В 99,995% случаев для современных плюсовиков они не важны.
                                      2) Есть простая проблема: nullability требует специфического программирования. Как минимум, банальные проверки на null и выделение объектов. Конечно, в интерпретируемом языке такие проверки можно вносить извне на месте создания переменных, приравниваия или некоторых обращений, но это чистой воды костыль.
                                      Я не говорю, что в них нет нужды, это даже несколько удобнее классических подходов, тем не менее, поддержка подобных проверок — Ад и Израиль, которую таже тимлиду врага не пожелаешь.


                                      1. ApeCoder
                                        01.04.2016 08:44

                                        2) В Котлине есть специальные операторы чтобы это делать было удобно. Это компилируемый язык.


                                        1. iCpu
                                          01.04.2016 09:10

                                          2.2) Сойдёмся на термине «транслируемый». Либо так, либо тысячи модов на майн не существуют. (Спойлер: они существуют). И, да, мне могут возразить «майн не на котлине написан». Но мне всё равно. Все жабошлюшки одинаковы, когда видят мой твёрдый decompiler.
                                          2.1) Внешние аннотации подключаются к Java-коду, про Kotlin речи нет. Если в коде изначально нет защиты от null, её придётся вводить извне. И не важно, на стороне котлина или в дополнительных классах, резутьтат один.


                                          1. ApeCoder
                                            01.04.2016 13:00

                                            2.2) Я не понял что вы написали.
                                            2.1) Да. Просто в Котлине вы можете этим удобно воспользоваться + свой код аннотировать легко. Изначально данные аннотации были введены чтобы IDEA могла ими пользоваться и не модифицировать библиотеки. Если есть возможность их модифицировать, можно воспользоваться атрибутом


                                            1. iCpu
                                              01.04.2016 13:50

                                              2.2) А вас не смущает возможность изменять поведение скомпилированного кода без внедрения специальных механизмов в этот самый код и само слово «скомпилированного» в одном предложении?
                                              2.1) Это прекрасно! Восхитительно! ЭТО ШЕДЕВР!!1! Такой реакции вы от меня ждали? Ну вот, забирайте.


                                              1. ApeCoder
                                                01.04.2016 14:22

                                                2.2) Никакого поведения скомпилированного кода не меняется — перечитайте описание. Меняется поведения компилятора при контроле типов при компиляции кусков которые используют этот код.
                                                2.1) Пожалуй, подойдет "Восхитительно". Спасибо.


                                                1. iCpu
                                                  01.04.2016 15:52
                                                  -1

                                                  Пусть будет по-вашему. Несмотря на то, что у вас очень странное понимание термина «компиляция», с нездоровым JVM уклоном. Но да ладно.


                                                  1. ApeCoder
                                                    01.04.2016 16:20
                                                    +2

                                                    У меня скорее с уклоном в абстрактное мышление :) совпадающее, впрочем, с точкой зрения авторов javaC, csC и прочих товарищей.


                                                  1. grossws
                                                    01.04.2016 23:18
                                                    +1

                                                    А clang — компилятор? Учитывая, что он компилирует в IR, который потом обрабатывается выбранным бэкендом и может закончить свою жизнь как в виде какого-нибудь условного байткода (wasm, asm.js), так и в виде бинарника.


                                                    1. iCpu
                                                      02.04.2016 04:18
                                                      -2

                                                      Компиляция — трансляция программного кода из ЯП высокого уровня в ЯП низкого уровня или машинные коды. При компиляции чаще всего выполняются дополнительные оптимизации кода, не позволяющие произвести обратный процесс — декомпиляцию. Самое банальное — ликвидация строковых имён из кода: комментариев, названий переменных. Ликбез закончен.
                                                      Теперь, умник, расскажи мне 3 вещи.
                                                      1) Как это так получилось, что jar-файлы можно декомпилировать в практически изначальный код?
                                                      2) Что в термине «транслятор» не позволяет сводить 1024 внешних языка в своё внутреннее представление?
                                                      3) Каким местом clang будет внедрять внешние нотации, о которых изначально говорилось в https://habrahabr.ru/post/280075/#comment_8833366 пункт 2?

                                                      А пока не ответил, карму откатил. У меня из-за вас, каналий, подсветка синтаксиса в комментариях не работает, что очень неудобно при ведении дискуссий.


                                                      1. grossws
                                                        02.04.2016 04:36

                                                        Теперь, умник, расскажи мне 3 вещи.

                                                        А пока не ответил, карму откатил. У меня из-за вас, каналий, подсветка синтаксиса в комментариях не работает, что очень неудобно при ведении дискуссий.

                                                        с нездоровым JVM уклоном

                                                        Для начала, не стоит хамить собеседникам.

                                                        Если же вернуться к вопросу что же такой компилятор, то в англоязычном сегменте обычно компилятор определяют как программу, которая транслирует исходный код на одном языке программирования в другой язык программирования, часто в asm или объектный код. Есть ещё source-to-source compiler'ы (transpiler'ы), которые компилируют из одного ЯП высокого уровня в другой ЯП высокого уровня. Например, RPython -> C или C -> JS (emscripten).


                                                        1. iCpu
                                                          02.04.2016 08:06

                                                          Когда мы будем в англоязычном сегменте, будем использовать англоязычные определения. Но мы пока не в англоязычном сегменте. Поэтому давайте использовать отечественные академические определения.
                                                          А они гласят, что компилятор — подмножество трансляторов. А clang — транслятор в LLVM и компилятор из LLVM в бинарики. Стандартная JVM — просто транслятор в байт-код с виртуальной средой выполнения. Чисто академически.

                                                          > Для начала, не стоит хамить собеседникам.
                                                          https://ru.wikipedia.org/wiki/Clang#.D0.9E.D0.B1.D0.B7.D0.BE.D1.80
                                                          Очень тяжело не хамить собеседникам, если они жонглируют терминами и влезают в середину диалога совершенно не в тему. Я был не прав, позволив себе сорваться. Однако ваши аргументы абсолютно не к месту.


                                                          1. webkumo
                                                            02.04.2016 10:40
                                                            +2

                                                            Чисто академически JVM — виртуальная машина, использующая в качестве машинных кодов подготовленный компилятором байткод.
                                                            «Чистая декомпиляция» в java — миф. Если иерархия классов ещё сохраняется, то «декомпилированный» код и близко не стоит с оригиналом (если не брать самые простые вещи)…


                                                            1. iCpu
                                                              02.04.2016 14:05

                                                              Мы можем потратить пол-века, выясняя, «транслятор» или «компилятор». Притом, что из промежуточно собраных class файлов JVM подготавливает ещё и слинкованный оптимизированный байт-код.
                                                              Мне интересно не это. Можем ли мы говорить о полноценно скомпилированном коде, если в него можно на ходу встраивать другой код и даже менять поведение кода под капотом? Но да ладно. Меня утомили эти споры на пустом месте.


                                                              1. grossws
                                                                02.04.2016 14:21
                                                                +1

                                                                Можем ли мы говорить о полноценно скомпилированном коде, если в него можно на ходу встраивать другой код и даже менять поведение кода под капотом?

                                                                Ага, а фон-неймановской архитектуры и страниц памяти с правами rwx не существует, да. Или нативный код под amd64 не "полноценно скомпилированный"?


                                                          1. grossws
                                                            02.04.2016 14:19
                                                            +1

                                                            Очень тяжело не хамить собеседникам, если они жонглируют терминами и влезают в середину диалога совершенно не в тему. Я был не прав, позволив себе сорваться. Однако ваши аргументы абсолютно не к месту.

                                                            А вы постарайтесь. Заодно и на низкую карму жаловаться не придётся. Кроме того, здесь ветки комментариев не являются приватными диалогами и в любой момент может подключиться кто угодно.


                                                            Когда мы будем в англоязычном сегменте, будем использовать англоязычные определения.

                                                            А использование термина "компилятор", являющегося калькой с английского вас не смущает?
                                                            А существование Jazelle, где байткод исполняется на голом процессоре?


                                                            1. iCpu
                                                              02.04.2016 14:45

                                                              > А использование термина «компилятор», являющегося калькой с английского вас не смущает?
                                                              Аргумент ниже пояса. У нас в толковом словаре для этого слова есть точно определённые значения. До тех пор, пока мы пишем на кириллице, мы используем именно эти значения. Не нравится, пишите термины на латинице, будем тянуть значения из оксфордского толковника.

                                                              И, да, трансляция, в общем, не обязана быть обратимой, она не о том. Она о преобразовании одного кода в другой. Любой другой.

                                                              > А существование Jazelle, где байткод исполняется на голом процессоре?
                                                              Он прям jar файл сжирает? Или ему нужно собрать программу в специальном формате?
                                                              А вас не смущает термин «JIT-компиляция», применяемый ко всем видам байт-кода? Интересно, что же происходит с «уже скомпилированным» байт-кодом во время этой самой компиляции?

                                                              > Ага, а фон-неймановской архитектуры и страниц памяти с правами rwx не существует, да. Или нативный код под amd64 не «полноценно скомпилированный»?
                                                              Внедрение в код с помощью только лишь xml-файла? Ну-ну, удачи.

                                                              > может подключиться кто угодно.
                                                              По теме. А вы в четвёртую сторону. Если желаете пообсуждать что-либо ещё, прямо скажите. А не встревайте с весьма поверхностными заявлениями посередь переписки.

                                                              > Заодно и на низкую карму жаловаться не придётся
                                                              Вам же приходится исходники без разметки читать, не мне. И ссылки без подсветки выделять. Я о ВАС, глупеньких, забочусь.


                                                              1. grossws
                                                                02.04.2016 15:53
                                                                +1

                                                                Он прям jar файл сжирает? Или ему нужно собрать программу в специальном формате?

                                                                А у вас процессор zip/tar.gz сжирает или требует специального формата? Если сделать ещё шаг — он ELF/PE сжирает или требует специального формата?

                                                                JAR — это просто zip-архив с метаинформацией. Можно его распаковать и собрать classpath руками или программно (как делают те же контейнеры, сама запускалка явы при использовании аргумента -jar/-cp).
                                                                А вас не смущает термин «JIT-компиляция», применяемый ко всем видам байт-кода? Интересно, что же происходит с «уже скомпилированным» байт-кодом во время этой самой компиляции?

                                                                Нет, не смущает. Компилируется в другое представление. Так же как компилятор, скажем Си может выдавать ассемблерный код, который будет ассемблироваться и линковаться далее.
                                                                Внедрение в код с помощью только лишь xml-файла? Ну-ну, удачи.

                                                                При чём здесь xml? То, что в некоторых библиотеках и тулзах это можно сделать xml'ем — всего лишь вопрос наличия библиотек. Реально всё делается на уровне генерации байткода другими библиотеками (javassist, asm) и загрузки класслоадером далее.

                                                                Никто не мешает в сишном или плюсовом коде подменять vtable после генерации нового бинарного кода тем же llvm. Или собирать .so/.dylib/.dll и использовать dlopen или его аналоги, как делает тот же Matlab. Если вам очень нужно — возьмите libxml2 и реализуйте аналогичное поведение. И, да, это написание своего рантайма. Так же народ делает свои модульные системы.
                                                                Вам же приходится исходники без разметки читать, не мне. И ссылки без подсветки выделять. Я о ВАС, глупеньких, забочусь.

                                                                Такими темпами это может перестать быть проблемой после достаточного минуса: будет сначала один комментарий в час, а потом и в сутки.


                                                                1. iCpu
                                                                  02.04.2016 16:28

                                                                  > При чём здесь xml?
                                                                  https://www.jetbrains.com/help/idea/2016.1/external-annotations.html?origin=old_help
                                                                  Я ничуть не сомневаюсь, что любой код может быть изменён на лету, было бы желание да привилегированный доступ. Разговор был о том, что IDEA позволяет внедрить в уже собранные библиотеки внешние нотации, дополнительные команды и, что немаловажно, внешние обработчики на другом ЯП.
                                                                  Я упаду в ноги тому человеку, который позволит вот так вот просто на лету менять хотя бы просто тип переменной или входного параметра какой-либо функции какой-нибудь dll.


                                                                  1. grossws
                                                                    02.04.2016 16:30

                                                                    Вы уверены, что понимаете разницу между managed и unmanaged окружениями?


                                                                    1. iCpu
                                                                      02.04.2016 16:35

                                                                      Есть что-нибудь, кроме виртуальной среды и, соответственно, виртуальной машины?


                                                                      1. grossws
                                                                        02.04.2016 17:21

                                                                        Например, dyninst, можно посмотреть на API.


                                                                        1. iCpu
                                                                          02.04.2016 18:04
                                                                          -2

                                                                          О, Господи, да кто ж спорит с тем, что можно патчить процессы? Усыпили, изменили память, разбудили, профит.
                                                                          Ладно, я понял. Вы победили. Всё, забирайте свою лаврушку и и идите лапать фотомоделей.