Agent a zmiana wartości stałych

0

Witam. Stworzyłem agenta, attachuje go do wybranej VM i staram się zmienić wartość stałej. Kod jest prawidłowy - kopiuję klase za to odpowiedzialną do innego projektu i uruchamiam w normalny sposób - działa.

    public static void setField(Object obj, Field field, String value) throws NoSuchFieldException {
        if (isParsable(field.getType())) {
            field.setAccessible(true);
            if ((field.getModifiers() & Modifier.FINAL) != 0) {
                Field modifiersField = Field.class.getDeclaredField("modifiers");
                modifiersField.setAccessible(true);
                try {
                    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
            try {
                field.set(obj, parsers.get(field.getType()).apply(value));
            } catch (IllegalAccessException e) {
                System.err.println("Exception! Modifiers: " + Modifier.toString(field.getModifiers()) + " Accessible: " + field.isAccessible());
                e.printStackTrace();
            }
        } else throw new Error("field needs to be primitive or String");
    }

Out:


Exception! Modifiers: public static Accessible: true
java.lang.IllegalAccessException: Can not set static final java.lang.Integer ...

Czy ktoś się kiedyś spotkał z czymś takim?

1

Podmiana stałych w runtime to bardzo nierozsadny pomysł. Pomyśl co się stanie z kodem w którym wartość została inlined. Dodatkowo jaka masz gwarancje że zjitowany kod innych klas które używają tej stałej będzie działał poprawnie?

0

Tak, zdaje sobię z tego sprawę. Jednak potrzebuje rozwiązania tego dość dziwnego problemu mimo wszystko. Wartości inlined też można zmieniać.

0

Po prześledzeniu src openjdk udało mi się znaleźć rozwiązanie. Jakby ktoś jeszcze miał taki problem:


            Method getAcc = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
            getAcc.setAccessible(true);
            FieldAccessor accessor = (FieldAccessor) getAcc.invoke(field, field);
            Field readOnly = accessor.getClass().getSuperclass().getDeclaredField("isReadOnly");
            readOnly.setAccessible(true);
            readOnly.set(accessor, false);
0

Ciekawy projekt masz może jakieś źródła na git hub. Czy przed zmianą wartości pól w klasach jakoś je instrumentujesz?

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0