Позвольте мне начать с небольшого теста Java.
Следующий код печатает «Hi, There»
Можете ли вы объяснить, как он это делает?

public class Test {
  public static void main(String args[]) {
    try {
      new ClassLoader() {
        public Class<?> findClass(String c) {
          byte[] bytecode = java.util.Base64.getDecoder().decode(
            "yv66vgAAADQAGAoABgAKCQALAAwIAA0KAA4ADwcAEAcAEQEABjxpb"+
            "l0PgEAAygpVgEABENvZGUMAAcACAcAEgwAEwAUAQAJSGksIHRoZXJ"+
            "lBwAVDAAWABcBAAFBAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEv"+
            "bGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhb"+
            "TsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMam"+
            "F2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAQABAAcACAABAAk"+
            "AAAAZAAIAAQAAAA0qtwABsgACEgO2AASxAAAAAAAA");
          return defineClass(“A”, bytecode, 0, bytecode.length);
        }
      }.loadClass(“A”).newInstance();
    } catch (Exception e) {
      throw new RuntimeException(e); 
    }
  }
}

Ответ таков:
Он делает это, создавая новый класс A и создавая его экземпляры. Конечно, класс А выглядит примерно так:

public class A {
  public A() { 
    System.out.println(“Hi, there”); 
  }
}

хотя, к сожалению, в Test.java вы не можете увидеть большую часть его кода.

Однако он присутствует в необработанном формате (байт-код), закодированном в строку base64.

Если вам интересно, строковое представление для A, как оно появляется в Test.java, может быть сгенерировано путем компиляции A.java и последующего доступа следующим образом:

URL url = A.class.getResource("A.class");
byte array[] = Files.readAllBytes(Paths.get(url.toURI()));
String bytecode = Base64.getEncoder().encodeToString(array);
System.out.println(bytecode); // this prints yv66vgAAADQAGAoAB…

В чем смысл ?

Итак, помимо невозможности чтения нашего кода (что очень плохо), есть ли какая-то польза от работы с необработанным байт-кодом, подобным этому?

Что ж, поскольку вы можете кодировать байт-код в фрагмент кода, теперь вы можете использовать другой подход к распространению своей работы и просить людей копировать и вставлять фрагмент кода в свою программу Java вместо того, чтобы загружать банка.

Конечно, этот подход подходит не всем, но в некоторых случаях он может оказаться полезным:

  1. демонстрации «попробуй, прежде чем использовать»
  2. Некоторые специализированные решения, в которых:
     – ваша библиотека очень легкая и не имеет зависимостей (или только зависимости, которые вы можете предположить, что они присутствуют в среде при ее интеграции)
     – ваш API минимален.
    - Сервис вашего инструмента является чисто аддитивным (например, приложения для мониторинга, профилировщики, анализаторы покрытия, регистраторы событий и т. д.).

Реальный пример

Я использовал этот подход в nudge4j.
nudge4j — это инструмент мониторинга для java-приложений, который обычно используется во время разработки.
Метод копирования/вставки показался мне идеальным.

Спасибо, что прочитали это.