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

StackOverflow https://stackoverflow.com/questions/106623

  •  01-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

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

Это было полезно?

Решение

Рассмотрите возможность модификации сторонних библиотек, чтобы они использовали seen для своих случайных экземпляров.Хотя у вас нет исходного кода, вы, вероятно, можете отредактировать байт-код, чтобы сделать это.Одним из полезных инструментов для этого является ASM.

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

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

Вам нужно будет ( как сказал анджаб ) изменить путь к классу bootstrap .

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

java -Xbootclasspath/p:C:\your andom_impl.jar Ваша программа

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

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

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

java -X

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

-Путь к Xbootclasspath/p:добавляйте перед путем к классу bootstrap

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

Удачи.

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

Сэм

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

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

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

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

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

BR, ~A

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

созданный jar из ThirdPartyClass.class

jar -cvf tpc.jar ThirdPartyClass.class

созданный jar из 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;
    }
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top