절대 재부팅되지 않는 테스트 환경을 구현하는 방법은 무엇입니까?


23

다음을 수행하는 방법에 대한 아이디어를 찾고 있습니다. Java로 간단한 "세계"를 작성하고 싶습니다. 나중에 새 객체를 시작하고 나중에 추가하여 기존 객체 간의 다른 동작을 시뮬레이션 / 관찰 할 수있는 것입니다. 그런 다음 이전 객체를 잠시 본 후 새로운 객체를 코딩 한 다음 기존 세계에로드 / 드롭합니다. 문제는 시작된 세계를 멈추거나 다시 시작하고 싶지 않고 몇 주 동안 실행하기를 원하지만 개체를 ​​삭제하고 다시 실행 / 다시 쓰기 / 삭제 / 생성 / 변경할 수있는 기능이 필요하다는 것입니다 재부팅하지 않아도 시간이 지남에 따라. 세계는 시각적으로 세계를 표현할 수있는 타일 맵 GUI를 사용하여 X / ​​Y 위치의 100 x 100 배열만큼 간단 할 수 있습니다. 나는 객체를 모니터링하고 각각에 '행동의 기회'를주기 위해 일종의 틱 타이머 프로세스가 필요하다는 것을 알고 있습니다.

예 : 월요일에 World.java를 코딩하고 실행 상태로 둡니다. 그런 다음 화요일에 Rock.java라는 새 클래스를 작성합니다 (이동하지 않음). 그런 다음 이미 실행중인이 세상에 (어떻게?)로드 / 드롭 (월드 배열에서 임의의 장소에 떨어 뜨리고 결코 움직이지 않습니다). 그런 다음 수요일에 Cat.java라는 새 클래스를 만들고이를 월드에 드롭하고 다시 무작위로 배치했지만이 새 오브젝트는 전 세계 (일부 단위 시간 이상)를 이동할 수 있으며 목요일에 Dog라는 클래스를 작성합니다. java는 또한 이동하지만 이웃 위치에 있으면 다른 객체에 대해 '동작'할 수 있으며 그 반대도 마찬가지입니다.

여기 있습니다. 미래 (및 현재 존재하지 않는) 객체를 감지 /로드 / 추적하는 방법을 알기 위해 실제 월드 클래스를 코딩 해야하는 구조 / 디자인의 종류를 모르겠습니다.

Java를 사용하여 이와 같은 작업을 수행하는 방법에 대한 아이디어가 있습니까?


2
핫 스와핑 처럼 들립니다 . 아마도 이것에 도움이 될만한 문헌이있을 것입니다. 어쨌든 매우 흥미로운 질문입니다. +1…
Konrad Rudolph

답변:


5

기본적으로 찾고있는 것은 핫 플러그 ​​가능 시스템입니다. 기본 애플리케이션을 실행 한 후 런타임시 이벤트 루프에 통합되는 플러그인을 추가하십시오. 먼저, 당신의 세계가 게임 엔터티로부터 무엇을 기대하는지 생각하십시오. 예를 들어 (설명에 따라) :

interface Entity {
   void init(World world);
   // Called when loaded for the first time in the world and adds itself
   // to the world (correct position in the array, scheduler for updates)

   void update(World world);
   // Called when scheduler fires (allows the entity to think about its
   // next move)

   Image getImage();
   // Called by the GUI when it is time to draw the entity on the screen
}

물론 필요하다고 생각되는 다른 방법을 추가 할 수 있습니다. 두 가지 관련 방법으로 World 매개 변수를 참고하십시오. 이를 통해 새 엔티티가 설정 또는 업데이트시 세계를 고려할 수 있습니다. 예를 들어, 개 반에서는 이웃에있는 모든 고양이를 세상에 요청할 수 있습니다. 다음으로이 인터페이스 및 Java 코드를 동적으로 컴파일 및로드하기위한 시스템과 작동하는 세상을 만듭니다. 이에 대한 예는 여기 에서 찾을 수 있습니다 .

void injectEntity(String filename, World world) {
    // Load the class as described in the mentioned link
    Entity e = (Entity) loadClass(filename);
    e.init(world);
}

World GUI에서이 메소드를 호출하여 새 엔티티를 추가하십시오. 월드 구현에 따라 Entity init 함수는 다음과 같습니다.

void init(World world) {
   // Register entity with world for easy access
   world.register(this, "RockImpl A");

   // Place the entity on the world map
   Point initialLocation = Point(10,5);
   world.place(this, initialLocation);

   // Schedule its update method for every 5 seconds
   world.schedule(this, 5);
}

1
Google 키워드 : "IoC 컨테이너", "제어 역전", "종속성 주입". 이들은 런타임시 구성 요소를 검색하고로드 할 수있는 일반적인 핫 플러그 ​​가능 시스템 기술입니다.
Nevermind

16

우리는 스턴 달 (Stendhal) 에서 급습을 위해 그런 일을했습니다.

우리는 재시작을 완전히 피하는 것을 목표로하지 않았습니다. 따라서 클라이언트 / 서버 통신과 같은 핵심 인프라 서비스를 변경하려면 다시 시작해야합니다. 그러나 엔티티, 생물 및 NPC를 추가하고 기존 객체를 수정하면 작동합니다. (아, 때로는 라이브 버그 수정, 리플렉션을 사용하여 개인 필드도 조작 할 수 있습니다)

다른 스킨과 같은 새로운 데이터를 기반으로 새로운 객체를 원할뿐만 아니라 새로운 행동을 추가하기를 원하기 때문에 월드 프로그램은 새로운 클래스 파일로드 할 수 있어야 합니다 . 이를 "스크립트"라고하지만 실제로 컴파일 된 Java 클래스입니다. 이러한 클래스는 Script.java 인터페이스를 구현합니다 .

Maria.java 는 간단한 예입니다. 그녀는 음료와 음식을 플레이어에게 판매하는 새로운 NPC입니다. 매우 복잡한 객체도 정의 할 수 있습니다.

새로운 클래스가 이런 식으로로드됩니다 :

// create a new class loader, with the script folder as classpath.
final File file = new File("./data/script");
final ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()});

// load class through new loader
final Class< ? > aClass = loader.loadClass(classname);
script = (Script) aClass.newInstance();

고유 한 이름을 보장하고 클래스를 언로드하지 않으려면 저수준 작업을 수행해야합니다.

그러나 언로드 는 매우 중요합니다. 이를 위해서는 새 코드를 삽입 할 때마다 새 클래스 로더를 인스턴스화해야합니다. 따라서 해당 코드에 대한 마지막 참조가 지워진 후 GC가 작업을 수행 할 수 있습니다.

우리는이 / 언로드 명령 우리의 인터페이스에서 호출하는 언로드 방법은 그 스크립트가 정리를 할 수 있다고합니다. 실제 언로드는 GC에 의해 자동으로 수행됩니다.

우리는 종종 공격 중에 많은 임시 개체를 만듭니다 . 그리고 우리는 습격이 끝난 후에 그것들을 모두 제거하기를 원합니다. 예를 들어 Gnomes Raid는 보이지 않는 관리자 근처에 여러 가지 격언을 낳습니다 . 이 코드를 사용합니다. GnomeRaid.java extends CreateRaid.java .

스크립트는 (첫 번째 예제에서 볼 수 있듯이) 세계에 직접 액세스하고 unload () 메소드에서 자체 정리를 수행 할 수 있습니다. 그러나 Java 코더는 정리하는 데 사용되지 않으며 성가시다. 따라서 스크립트에서 사용할 수 있는 샌드 박스 를 만들었습니다 . 언로드시 샌드 박스 클래스를 통해 월드에 추가 된 모든 객체가 제거됩니다.


3

세계 (말장난 의도 없음)와 모든 상태 (위치, 속도, 모든 변수)를 저장하십시오.

  • 프로그램을 닫습니다.
  • 변경 사항을 구현하십시오 (저장과의 역 호환성을 보장).
  • 프로그램을 다시 컴파일하십시오.
  • 프로그램을 다시 시작하십시오.
  • 세계와 국가를로드하십시오.
  • 반복

이것은 일반적인 해결책이지만, 원하는대로 코드 블록과 클래스를 동적으로 구현할 수 있는지 알 수있는 Java 사양은 아닙니다 ...

옵션 2 는 즉시로드 할 수있는 스크립팅 언어를 바인딩하는 것입니다.


스크립팅 언어의 경우 +1 Java에 바인딩되지 않은 경우 LPC 기반 MUD 드라이버 및 mudlib도 사용해보십시오.
Martin Sojka

1

Java의 경우 OSGi 플랫폼있으면됩니다 . 따라서 모듈이나 응용 프로그램을 핫 스왑하는 것은 쉽지 않으며 원격 관리 또는 부분 업그레이드도 수행합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.