Как я могу дать java.util.Random конкретное семя в сторонних классах?

У меня есть программа Java, которая загружает файлы сторонних классов (классы, которые я не писал) и выполняет их. Эти классы часто используют java.util.Random, который по умолчанию генерирует случайные начальные начальные значения при каждом создании экземпляра. Из соображений воспроизводимости я хочу каждый раз давать этим классам одно и то же начальное значение, меняя его только по своему усмотрению.

Вот некоторые из очевидных решений и почему они не работают:

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

  2. Используйте собственный загрузчик классов, чтобы загрузить наш собственный класс Random вместо версии JVM. Этот подход не будет работать, потому что Java не позволяет загрузчикам классов переопределять классы в пакете java.

  3. Замените реализацию java.util.Random в rt.jar на нашу собственную или поместите файлы в надежные места для JVM. Эти подходы требуют, чтобы пользователь приложения возился с установкой JVM на своем компьютере, и они бесполезны.

  4. Добавление пользовательского класса java.util.Random в путь к загрузочному классу. Хотя это технически сработает, для данного конкретного приложения это непрактично, поскольку это приложение предназначено для запуска конечными пользователями из среды IDE. Я хочу сделать запуск приложения удобным для пользователей, а это значит, что заставлять их устанавливать путь к загрузочному классу - это боль. Я не могу скрыть это в сценарии, потому что он предназначен для запуска из среды IDE, такой как Eclipse (для упрощения отладки).

Так как я могу это сделать?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
0
1 494
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вы можете использовать АОП, чтобы перехватывать вызовы Random и менять аргумент на то, что вы хотите.

Сэм

«Используйте собственный загрузчик классов, чтобы загрузить наш собственный класс Random вместо версии JVM. Этот подход не будет работать, потому что Java не позволяет загрузчикам классов переопределять классы в пакете java».

как насчет изменения пути к загрузочному классу для использования вашего собственного класса Random?

BR, ~ А

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

adum 20.09.2008 05:12

Хотя вы не можете тривиально изменить загрузчик классов для пакетов «java.x» и «sun.x», есть способ учесть загрузку класса (и установить прослушиватель «после того, как класс был закодирован и загружен») этих классов, так что вы может установить что-то вроде семени после загрузки классов из этих пакетов. Подсказка: используйте отражение.

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

P.S .: Имейте в виду, что "static {}" - блоки могут снова помешать вам возиться с семенами.

Ваш вариант 2 действительно будет работать со следующими указаниями.

Вам нужно будет (как сказал Анджаб) изменить путь к классу начальной загрузки.

В командной строке программы нужно добавить следующее:

java -Xbootclasspath / p: C: \ your \ random_impl.jar YourProgram

Предполагая, что вы находитесь на машине Windown или пути в любой ОС.

Эта опция добавляет классы в файлы jar до загрузки rt.jar. Таким образом, ваш Random будет загружен раньше, чем это сделает класс rt.jar Random.

Использование отображается путем ввода:

java -X

Он отображает все функции X (tra), которые есть в JVM. Это может быть недоступно на других реализациях виртуальных машин, таких как JRockit или другие, но есть на Sun JVM.

-Xbootclasspath / p: добавить перед путем к классу начальной загрузки

Я использовал этот подход в приложении, где класс ORB по умолчанию должен быть заменен другой реализацией ORB. Класс ORB является частью Java Core и никогда не имел никаких проблем.

Удачи.

Ответ принят как подходящий

Подумайте об изменении сторонних библиотек, чтобы они использовали видимое для своих экземпляров Random. Хотя у вас нет исходного кода, вы, вероятно, можете отредактировать байт-код, чтобы сделать это. Один из полезных инструментов для этого - КАК М.

Да вариант 2 работает: созданы два класса для целей тестирования с именами ThirdPartyClass.java и Random.java

создал банку из ThirdPartyClass.class

jar -cvf tpc.jar ThirdPartyClass.class

создал банку из Random.class

jar -cvf rt123.jar Random.class

после этого выполните следующую команду:

java  -Xbootclasspath/p:tcp.jar:rt123.jar -cp . -verbose ThirdPartyClass

На выходе будет: seed value for ThirdPartyClass-> 1.

исходный код ThirdPartyClass.java ----->

import java.util.Random;

public class ThirdPartyClass {
    ThirdPartyClass(long seed ) {
        System.out.println("seed value for ThirdPartyClass-> "+seed);
    }   

    public static void main(String [] args) {
        ThirdPartyClass tpc=new ThirdPartyClass(new Random().nextLong());
    }
}

исходный код Random.java ------->

package java.util;

import java.io.Serializable;

public class Random extends Object implements Serializable
{
    public Random() {
    }

    public Random(long seed) {
    }

    public long nextLong() {
        return 1;
    }
}

Спасибо Махавир Прасад Мали

Другие вопросы по теме