Bug 576774: [RJ-Servi] Migrate to java.time API

Also:
  - Rename some config properties to more meaningful names
  - Fix display names of properties in MXBeans

Change-Id: I120cc837e51e321f01ca06122c103ce2d3d96b37
diff --git a/CHANGES.md b/CHANGES.md
index 558c592..2e0951f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -3,6 +3,8 @@
 
 ## RJ 4.5.0 ~ StatET 4.5.0
 
+### Services
+
   * The data access for tool command handler is enhanced. Implementations of handlers need to be
     adapted.
     
@@ -13,6 +15,15 @@
     
     (Bug 574779)
 
+### RServi Node and Pool
+
+  * The configuration and pool API is migrated to make use of `java.time`. Timestamps are
+    represented by `Instant` and durations like timeouts by `Duration`, except in MXBeans.
+    In the config classes also some related properties are renamed to more meaningful names.
+    For property accessors, which still use long for timestamps and durations, the postfix `Millis`
+    is added to their names.
+    Applications need to be adapted. (Bug 576774)
+
 
 ## RJ 4.4.0 ~ StatET 4.4.0
 
diff --git a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
index a7ea932..24b2e91 100644
--- a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
+++ b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
@@ -14,8 +14,6 @@
 
 package org.eclipse.statet.rj.servi.pool;
 
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -28,6 +26,7 @@
 
 import static org.eclipse.statet.internal.rj.servi.APool2.CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY;
 
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -36,6 +35,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 import javax.security.auth.login.LoginException;
 
@@ -70,9 +70,9 @@
 public class JMPoolTest extends AbstractServiTest {
 	
 	
-	private static int NODE_STARTUP_MILLIS= 7_000;
+	private static Duration NODE_STARTUP_DURATION= Duration.ofSeconds(7);
 	
-	private static int WAIT_IDLE_MILLIS= 30_000;
+	private static Duration WAIT_IDLE_DURATION= Duration.ofSeconds(30);
 	
 	private static double TIME_TOLERANCE_MILLIS= 10;
 	
@@ -230,7 +230,7 @@
 	}
 	
 	@Test
-	public void TotalNodes_borrowMax() throws Exception,
+	public void TotalNodes_allocateMax() throws Exception,
 			InterruptedException {
 		final PoolConfig poolConfig= new PoolConfig();
 		poolConfig.setMaxTotalCount(2);
@@ -243,7 +243,7 @@
 		assertNodeOperative(servi1);
 		assertNodeOperative(servi2);
 		
-		Thread.sleep(WAIT_IDLE_MILLIS);
+		Thread.sleep(WAIT_IDLE_DURATION.toMillis());
 		assertIdleCount(0);
 		
 		closeServi(servi1);
@@ -251,11 +251,12 @@
 	}
 	
 	@Test
-	public void TotalNodes_borrowTimeout() throws Exception {
+	public void TotalNodes_allocateTimeout() throws Exception {
 		final PoolConfig poolConfig= new PoolConfig();
 		poolConfig.setMaxTotalCount(2);
 		this.server.setPoolConfig(poolConfig);
 		this.server.start();
+		final var timeout= nonNullAssert(poolConfig.getAllocationTimeout());
 		
 		final RServi servi1= getServi("test1");
 		assertNotNull(servi1);
@@ -263,10 +264,10 @@
 		final long t2= System.nanoTime();
 		final RServi servi2= getServi("test2");
 		assertNotNull(servi2);
-		{	final long d2= TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t2);
-			final long dMax= poolConfig.getMaxWaitTime() + NODE_STARTUP_MILLIS;
-			assertTrue(d2 < dMax,
-					() -> String.format("duration expected: < %1$sms, actual: %2$sms", dMax, d2) );
+		{	final Duration d2= Duration.ofNanos(System.nanoTime() - t2);
+			final Duration dMax= timeout.plus(NODE_STARTUP_DURATION);
+			assertTrue(d2.compareTo(dMax) < 0, () ->
+					String.format("duration expected: < %1$sms, actual: %2$sms", dMax, d2) );
 		}
 		
 		final long t3= System.nanoTime();
@@ -276,16 +277,17 @@
 			throw new AssertionError("totalCount");
 		}
 		catch (final NoSuchElementException e) {
-			final long d3= TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t3);
-			final long dExpected= poolConfig.getMaxWaitTime();
-			final long dTol= 500;
-			assertTrue(d3 > poolConfig.getMaxWaitTime() - dTol && d3 < poolConfig.getMaxWaitTime() + dTol,
-					() -> String.format("duration expected: %1$sms (±%3$sms), actual: %2$sms", dExpected, d3, dTol));
+			final Duration d3= Duration.ofNanos(System.nanoTime() - t3);
+			final Duration dExpected= timeout;
+			final double deltaMillis= 500;
+			assertDurationEquals(dExpected, d3, deltaMillis, () ->
+					String.format("duration expected: %1$sms (±%3$sms), actual: %2$sms",
+							dExpected, d3, deltaMillis ));
 		}
 	}
 	
 	@Test
-	public void UsageCount_borrowMax() throws Exception {
+	public void UsageCount_allocateMax() throws Exception {
 		final ProgressMonitor m1= new NullProgressMonitor();
 		final ProgressMonitor m2= new NullProgressMonitor();
 		
@@ -327,7 +329,7 @@
 			final PoolNodeObject node1= assertSinglePoolNode();
 			
 			awaitStateCondition(node1, (state) -> (state != PoolNodeState.ALLOCATED),
-					(int)(1.2 * periodMillis) + WAIT_IDLE_MILLIS );
+					Duration.ofMillis((long)(1.2 * periodMillis)).plus(WAIT_IDLE_DURATION) );
 			skipChecking(node1);
 			assertEquals(PoolNodeState.ALLOCATED, node1.getState());
 			assertNodeOperative(servi1);
@@ -359,7 +361,7 @@
 			clientCheckJob.cancel(false);
 			
 			awaitStateCondition(node1, (state) -> (state != PoolNodeState.ALLOCATED),
-					(int)(1.2 * periodMillis) + WAIT_IDLE_MILLIS );
+					Duration.ofMillis((long)(1.2 * periodMillis)).plus(WAIT_IDLE_DURATION) );
 			skipChecking(node1);
 			assertDisposingToDisposed(node1);
 			
@@ -463,7 +465,7 @@
 		skipChecking(node1);
 		assertEquals(PoolNodeState.IDLING, node1.getState());
 		
-		node1.evict(0);
+		node1.evict(null);
 		assertDisposingToDisposed(node1);
 	}
 	
@@ -514,22 +516,31 @@
 		this.server.setPoolConfig(poolConfig);
 		this.server.start();
 		
+		Duration actual;
+		
 		assertIdleCount(1);
 		final PoolNodeObject node1= assertSinglePoolNode();
-		assertEquals(-1, node1.getLastestAllocationDuration(), "duration");
+		actual= node1.getLastestAllocationDuration();
+		assertNull(actual, "duration");
 		
 		final long startNanos= System.nanoTime();
 		final RServi servi1= getServi("test1");
-		assertEquals(NANOSECONDS.toMillis(System.nanoTime() - startNanos), node1.getLastestAllocationDuration(),
+		actual= node1.getLastestAllocationDuration();
+		assertNotNull(actual);
+		assertDurationEquals(Duration.ofNanos(System.nanoTime() - startNanos), actual,
 				TIME_TOLERANCE_MILLIS, "duration" );
 		
 		Thread.sleep(3000);
-		assertEquals(NANOSECONDS.toMillis(System.nanoTime() - startNanos), node1.getLastestAllocationDuration(),
+		actual= node1.getLastestAllocationDuration();
+		assertNotNull(actual);
+		assertDurationEquals(Duration.ofNanos(System.nanoTime() - startNanos), actual,
 				TIME_TOLERANCE_MILLIS, "duration" );
 		
 		final long endNanos= System.nanoTime();
 		closeServi(servi1);
-		assertEquals(NANOSECONDS.toMillis(endNanos - startNanos), node1.getLastestAllocationDuration(),
+		actual= node1.getLastestAllocationDuration();
+		assertNotNull(actual);
+		assertDurationEquals(Duration.ofNanos(endNanos - startNanos), actual,
 				TIME_TOLERANCE_MILLIS, "duration" );
 	}
 	
@@ -546,7 +557,7 @@
 		
 		final PoolNodeObject node1= assertSinglePoolNode();
 		closeServi(servi1);
-		node1.evict(0);
+		node1.evict(null);
 		
 		skipChecking(node1);
 		assertDisposingToDisposed(node1);
@@ -564,7 +575,7 @@
 		
 		final PoolNodeObject node1= assertSinglePoolNode();
 		assertEquals(PoolNodeState.ALLOCATED, node1.getState());
-		node1.evict(0);
+		node1.evict(null);
 		
 		skipChecking(node1);
 		assertDisposingToDisposed(node1);
@@ -602,7 +613,7 @@
 		}
 		final PoolNodeObject node1= assertSinglePoolNode();
 		assertEquals(PoolNodeState.ALLOCATED, node1.getState());
-		node1.evict(0);
+		node1.evict(null);
 		
 		skipChecking(node1);
 		assertDisposingToDisposed(node1);
@@ -626,7 +637,7 @@
 		final Process process= nonNullAssert((Process)nodeHandler.getFieldObj("process"));
 		process.destroy();
 		
-		node1.evict(0);
+		node1.evict(null);
 		
 		skipChecking(node1);
 		assertDisposingToDisposed(node1);
@@ -663,7 +674,7 @@
 			if (expected == poolStatus.getNumIdling()) {
 				return;
 			}
-			if (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t) > WAIT_IDLE_MILLIS) {
+			if (System.nanoTime() - t > WAIT_IDLE_DURATION.toNanos()) {
 				assertEquals(expected, poolStatus.getNumIdling(), "num idle");
 			}
 			Thread.sleep(100);
@@ -671,17 +682,17 @@
 	}
 	
 	private void skipChecking(final PoolNodeObject node) throws InterruptedException {
-		awaitStateCondition(node, (state) -> (state != PoolNodeState.CHECKING), WAIT_IDLE_MILLIS);
+		awaitStateCondition(node, (state) -> (state != PoolNodeState.CHECKING), WAIT_IDLE_DURATION);
 	}
 	
 	private void awaitStateCondition(final PoolNodeObject node,
-			final Predicate<PoolNodeState> condition, final int timeoutMillis) throws InterruptedException {
+			final Predicate<PoolNodeState> condition, final Duration timeout) throws InterruptedException {
 		final long t= System.nanoTime();
 		while (true) {
 			if (condition.test(node.getState())) {
 				return;
 			}
-			if (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t) > timeoutMillis) {
+			if (System.nanoTime() - t > timeout.toNanos()) {
 				return;
 			}
 			Thread.sleep(100);
@@ -696,9 +707,19 @@
 			assertEquals(PoolNodeState.DISPOSING, state, "state");
 		}
 		
-		awaitStateCondition(node, (state) -> (state != PoolNodeState.DISPOSING), WAIT_IDLE_MILLIS);
+		awaitStateCondition(node, (state) -> (state != PoolNodeState.DISPOSING), WAIT_IDLE_DURATION);
 		
 		assertEquals(PoolNodeState.DISPOSED, node.getState(), "state");
 	}
 	
+	private void assertDurationEquals(final Duration expected, final Duration actual,
+			final double deltaMillis, final String message) {
+		assertEquals(expected.toMillis(), actual.toMillis(), deltaMillis, message);
+	}
+	
+	private void assertDurationEquals(final Duration expected, final Duration actual,
+			final double deltaMillis, final Supplier<String> messageSupplier) {
+		assertEquals(expected.toMillis(), actual.toMillis(), deltaMillis, messageSupplier);
+	}
+	
 }
diff --git a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/LocalNodeTest.java b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/LocalNodeTest.java
index 8371cb5..96527cc 100644
--- a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/LocalNodeTest.java
+++ b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/LocalNodeTest.java
@@ -20,8 +20,8 @@
 
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.time.Duration;
 import java.util.NoSuchElementException;
-import java.util.concurrent.TimeUnit;
 
 import javax.management.OperationsException;
 import javax.security.auth.login.LoginException;
@@ -191,9 +191,9 @@
 		
 		final long t1= System.nanoTime();
 		this.localR.stop();
-		final long d1= TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1);
-		final long dMax= new RServiNodeConfig().getStartStopTimeout() + 1500;
-		assertTrue(d1 < new RServiNodeConfig().getStartStopTimeout() + 1500,
+		final Duration d1= Duration.ofNanos(System.nanoTime() - t1);
+		final Duration dMax= new RServiNodeConfig().getStartStopTimeout().plusMillis(1500);
+		assertTrue(d1.compareTo(dMax) < 0,
 				() -> String.format("duration expected: < %1$sms, actual: %2$sms", dMax, d1) );
 	}
 	
diff --git a/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolItemBean.java b/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolItemBean.java
index dfe0447..3ca6878 100644
--- a/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolItemBean.java
+++ b/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolItemBean.java
@@ -14,6 +14,10 @@
 
 package org.eclipse.statet.rj.servi.webapp;
 
+import java.time.Instant;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
 import org.eclipse.statet.jcommons.rmi.RMIAddress;
 
 import org.eclipse.statet.rj.RjException;
@@ -23,21 +27,22 @@
 import org.eclipse.statet.rj.servi.pool.PoolServer;
 
 
+@NonNullByDefault
 public class PoolItemBean extends PoolNodeItem {
 	
 	
-	public PoolItemBean(final PoolNodeObject poolObj, final long stamp) {
+	public PoolItemBean(final PoolNodeObject poolObj, final Instant stamp) {
 		super(poolObj, stamp);
 	}
 	
 	
-	public String getRMIAddress() {
+	public @Nullable String getRMIAddress() {
 		final RMIAddress address= getAddress();
 		return (address != null) ? address.getAddress() : null;
 	}
 	
 	
-	public String actionEnableConsole() {
+	public @Nullable String actionEnableConsole() {
 		try {
 			super.enableConsole("none");
 		}
@@ -47,7 +52,7 @@
 		return null;
 	}
 	
-	public String actionDisableConsole() {
+	public @Nullable String actionDisableConsole() {
 		try {
 			super.disableConsole();
 		}
@@ -67,7 +72,7 @@
 	}
 	
 	public void actionKill() {
-		evict(0);
+		evict(null);
 	}
 	
 }
diff --git a/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolStatusBean.java b/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolStatusBean.java
index bb23c7f..1800e8a 100644
--- a/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolStatusBean.java
+++ b/servi/org.eclipse.statet.rj.servi.webapp/src/main/java/org/eclipse/statet/rj/servi/webapp/PoolStatusBean.java
@@ -14,14 +14,20 @@
 
 package org.eclipse.statet.rj.servi.webapp;
 
+import java.time.Instant;
+
 import javax.annotation.PostConstruct;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.rj.servi.pool.PoolNodeItem;
 import org.eclipse.statet.rj.servi.pool.PoolNodeObject;
 import org.eclipse.statet.rj.servi.pool.PoolStatus;
 import org.eclipse.statet.rj.servi.pool.RServiPoolManager;
 
 
+@NonNullByDefault
 public class PoolStatusBean extends PoolStatus<PoolItemBean> {
 	
 	
@@ -40,7 +46,7 @@
 	}
 	
 	private void load() {
-		final long stamp= System.currentTimeMillis();
+		final Instant stamp= Instant.now();
 		final RServiPoolManager poolManager= this.server.getManager();
 		if (poolManager == null) {
 			FacesUtils.addErrorMessage(null, "The pool is currently not available.");
@@ -49,7 +55,7 @@
 	}
 	
 	@Override
-	protected PoolNodeItem createPoolItem(final PoolNodeObject itemData, final long stamp) {
+	protected PoolNodeItem createPoolItem(final PoolNodeObject itemData, final Instant stamp) {
 		return new PoolItemBean(itemData, stamp);
 	}
 	
@@ -59,7 +65,7 @@
 	}
 	
 	
-	public synchronized long getStamp() {
+	public synchronized Instant getStamp() {
 		check();
 		return super.getStatusStamp();
 	}
@@ -76,16 +82,16 @@
 	}
 	
 	
-	public String actionRefresh() {
+	public @Nullable String actionRefresh() {
 		return null;
 	}
 	
-	public synchronized String actionEnableAutoRefresh() {
+	public synchronized @Nullable String actionEnableAutoRefresh() {
 		this.autoRefresh= true;
 		return null;
 	}
 	
-	public synchronized String actionDisableAutoRefresh() {
+	public synchronized @Nullable String actionDisableAutoRefresh() {
 		this.autoRefresh= false;
 		return null;
 	}
diff --git a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/LocalNodeFactory.java b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/LocalNodeFactory.java
index 5737c0e..464a3a0 100644
--- a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/LocalNodeFactory.java
+++ b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/LocalNodeFactory.java
@@ -425,15 +425,12 @@
 		
 		p.rStartupSnippet= config.getRStartupSnippet();
 		
-		long timeout= config.getStartStopTimeout();
-		if (timeout > 0) {
-			timeout= TimeUnit.MILLISECONDS.toNanos(timeout);
-		}
+		final var timeout= config.getStartStopTimeout();
 		synchronized (this) {
 			this.verbose= config.getEnableVerbose();
 			this.baseConfig= config;
 			this.processConfig= p;
-			this.timeoutNanos= timeout;
+			this.timeoutNanos= (timeout != null) ? timeout.toNanos() : -1;
 		}
 	}
 	
diff --git a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/NodeHandler.java b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/NodeHandler.java
index 892e741..b5a66f0 100644
--- a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/NodeHandler.java
+++ b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/NodeHandler.java
@@ -19,6 +19,7 @@
 
 import java.nio.file.Path;
 import java.rmi.RemoteException;
+import java.time.Instant;
 
 import org.eclipse.statet.jcommons.lang.NonNullByDefault;
 import org.eclipse.statet.jcommons.lang.Nullable;
@@ -47,11 +48,10 @@
 	
 	boolean isConsoleEnabled;
 	
-	private long shutdownTime;
+	private @Nullable Instant shutdownTime;
 	
 	
 	public NodeHandler() {
-		this.shutdownTime= -1;
 	}
 	
 	
@@ -111,7 +111,7 @@
 	}
 	
 	void shutdown() throws RemoteException {
-		this.shutdownTime= System.currentTimeMillis();
+		this.shutdownTime= Instant.now();
 		this.clientHandler= null;
 		setClientLabel(null);
 		final RServiNode node= this.node;
@@ -137,7 +137,10 @@
 		return this.clientLabel;
 	}
 	
-	public long getShutdownTime() {
+	/**
+	 * @since 4.5
+	 */
+	public @Nullable Instant getShutdownTime() {
 		return this.shutdownTime;
 	}
 	
diff --git a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/Utils.java b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/Utils.java
index d0f817a..65e1426 100644
--- a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/Utils.java
+++ b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/internal/rj/servi/Utils.java
@@ -16,6 +16,7 @@
 
 import static org.eclipse.statet.jcommons.lang.SystemUtils.OS_WIN;
 
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
@@ -191,6 +192,74 @@
 	}
 	
 	
+	public static boolean isNegative(final @Nullable Duration duration) {
+		return (duration != null && duration.isNegative());
+	}
+	
+	
+	private static boolean isSign(final char c) {
+		return (c == '+' || c == '-');
+	}
+	
+	private static boolean isDigit(final char c) {
+		return (c >= '0' && c <= '9');
+	}
+	
+	public static Duration parseDuration(final String s) {
+		if (!s.isEmpty()
+				&& (isSign(s.charAt(0)) ?
+						s.length() >= 2 && isDigit(s.charAt(1)) :
+						isDigit(s.charAt(0)) )) {
+			final long millis= Long.parseLong(s);
+			return Duration.ofMillis(millis);
+		}
+		return Duration.parse(s);
+	}
+	
+	public static Duration parseDuration(final @Nullable String s,
+			final Duration defaultValue) {
+		if (s == null) {
+			return defaultValue;
+		}
+		return parseDuration(s);
+	}
+	
+	public static String serDuration(final Duration duration) {
+		return Long.toString(duration.toMillis());
+	}
+	
+	public static @Nullable Duration parseNullableDuration(final String s) {
+		if (s.isEmpty()) {
+			return null;
+		}
+		if ((isSign(s.charAt(0)) ?
+				s.length() >= 2 && isDigit(s.charAt(1)) :
+				isDigit(s.charAt(0)) )) {
+			final long millis= Long.parseLong(s);
+			if (millis == -1) {
+				return null;
+			}
+			return Duration.ofMillis(millis);
+		}
+		return Duration.parse(s);
+	}
+	
+	public static @Nullable Duration parseNullableDuration(final @Nullable String s,
+			final Duration defaultValue) {
+		if (s == null) {
+			return defaultValue;
+		}
+		return parseNullableDuration(s);
+	}
+	
+	public static String serNullableDuration(final @Nullable Duration duration) {
+		if (duration == null) {
+			return "-1"; // for backward compatibility  //$NON-NLS-1$
+		}
+		return Long.toString(duration.toMillis());
+	}
+	
+	
 	private Utils() {
 	}
 	
diff --git a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/rj/servi/node/RServiNodeConfig.java b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/rj/servi/node/RServiNodeConfig.java
index 2f8d245..4f15f9f 100644
--- a/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/rj/servi/node/RServiNodeConfig.java
+++ b/servi/org.eclipse.statet.rj.servi/src/org/eclipse/statet/rj/servi/node/RServiNodeConfig.java
@@ -14,10 +14,13 @@
 
 package org.eclipse.statet.rj.servi.node;
 
+import static org.eclipse.statet.internal.rj.servi.Utils.isNegative;
+
 import java.io.File;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
+import java.time.Duration;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -73,11 +76,12 @@
 	 * Property id for timeout of start/stop of nodes
 	 * 
 	 * @see #setStartStopTimeout(long)
-	 * @since 2.0
 	 */
-	public static final String STARTSTOP_TIMEOUT__ID= "startstop_timeout.millis";
+	public static final String STARTSTOP_TIMEOUT_ID= "startstop_timeout.millis";
+	@Deprecated
+	public static final String STARTSTOP_TIMEOUT__ID= STARTSTOP_TIMEOUT_ID;
 	
-	private static final long STARTSTOP_TIMEOUT_DEFAULT= 10 * 1000;
+	private static final Duration STARTSTOP_TIMEOUT_DEFAULT= Duration.ofSeconds(10);
 	
 	
 	private @Nullable String rHome;
@@ -96,7 +100,7 @@
 	private boolean enableConsole;
 	private boolean enableVerbose;
 	
-	private long startStopTimeout;
+	private @Nullable Duration startStopTimeout;
 	
 	
 	public RServiNodeConfig() {
@@ -174,11 +178,13 @@
 		setNodeArgs(map.getProperty(NODE_ARGS_ID));
 		setBaseWorkingDirectory(map.getProperty(BASE_WD_ID));
 		setRStartupSnippet(map.getProperty(R_STARTUP_SNIPPET_ID));
-		setEnableConsole(Boolean.parseBoolean(map.getProperty(CONSOLE_ENABLED_ID)));
-		setEnableVerbose(Boolean.parseBoolean(map.getProperty(VERBOSE_ENABLED_ID)));
-		{	final String s= map.getProperty(STARTSTOP_TIMEOUT__ID);
-			this.startStopTimeout= ((s != null) ? Long.parseLong(s) : STARTSTOP_TIMEOUT_DEFAULT);
-		}
+		setEnableConsole(Boolean.parseBoolean(
+				map.getProperty(CONSOLE_ENABLED_ID) ));
+		setEnableVerbose(Boolean.parseBoolean(
+				map.getProperty(VERBOSE_ENABLED_ID) ));
+		this.startStopTimeout= Utils.parseNullableDuration(
+				map.getProperty(STARTSTOP_TIMEOUT_ID),
+				STARTSTOP_TIMEOUT_DEFAULT );
 	}
 	
 	@Override
@@ -195,7 +201,7 @@
 		Utils.setProperty(map, R_STARTUP_SNIPPET_ID, this.rStartupSnippet);
 		Utils.setProperty(map, CONSOLE_ENABLED_ID, Boolean.toString(this.enableConsole));
 		Utils.setProperty(map, VERBOSE_ENABLED_ID, Boolean.toString(this.enableVerbose));
-		Utils.setProperty(map, STARTSTOP_TIMEOUT__ID, Long.toString(this.startStopTimeout));
+		Utils.setProperty(map, STARTSTOP_TIMEOUT_ID, Utils.serNullableDuration(this.startStopTimeout));
 	}
 	
 	public synchronized void setRHome(final @Nullable String path) {
@@ -311,23 +317,23 @@
 	/**
 	 * Returns the timeout of start/stop of nodes
 	 * 
-	 * @return the timeout in milliseconds
+	 * @return the timeout or {@code null} if timeout is disabled
 	 * 
-	 * @since 2.0
+	 * @since 4.5
 	 */
-	public long getStartStopTimeout() {
+	public synchronized @Nullable Duration getStartStopTimeout() {
 		return this.startStopTimeout;
 	}
 	
 	/**
 	 * Sets the timeout of start/stop of nodes
 	 * 
-	 * @param milliseconds the timeout in milliseconds
+	 * @param timeout the timeout (> 0) or {@code null} to disable timeout
 	 * 
-	 * @since 2.0
+	 * @since 4.5
 	 */
-	public void setStartStopTimeout(final long milliseconds) {
-		this.startStopTimeout= milliseconds;
+	public synchronized void setStartStopTimeout(final @Nullable Duration timeout) {
+		this.startStopTimeout= timeout;
 	}
 	
 	
@@ -339,9 +345,9 @@
 		valid&= isDirectoryPropertyValid(JAVA_HOME_ID, this.javaHome, messages);
 		valid&= isDirectoryPropertyValid(BASE_WD_ID, this.baseWd, messages);
 		
-		if (this.startStopTimeout != -1 && this.startStopTimeout < 0) {
+		if (isNegative(this.startStopTimeout)) {
 			if (messages != null) {
-				messages.add(new ValidationMessage(STARTSTOP_TIMEOUT__ID, "Value must be > 0 or -1 (infinite)."));
+				messages.add(new ValidationMessage(STARTSTOP_TIMEOUT_ID, "Value must be > 0 or unset/-1 (infinite)."));
 			}
 			valid= false;
 		}
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java
index c1ee7e9..0a298f6 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java
@@ -14,6 +14,10 @@
 
 package org.eclipse.statet.internal.rj.servi;
 
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullElse;
+
+import java.time.Duration;
+
 import org.apache.commons.pool2.PooledObject;
 import org.apache.commons.pool2.PooledObjectState;
 import org.apache.commons.pool2.impl.DefaultEvictionPolicy;
@@ -24,6 +28,7 @@
 
 import org.eclipse.statet.jcommons.collections.ImList;
 import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
 
 import org.eclipse.statet.rj.RjInvalidConfigurationException;
 import org.eclipse.statet.rj.servi.pool.PoolConfig;
@@ -44,6 +49,8 @@
 	private static final byte CLOSED= 4;
 	
 	
+	private static final Duration DISABLE_DURATION= Duration.ofMillis(-1);
+	
 	private static final EvictionPolicy<APool2NodeHandler> EVICTION_POLICY= new DefaultEvictionPolicy<>() {
 		
 		@Override
@@ -65,14 +72,14 @@
 		aConfig.setTestOnBorrow(false);
 		aConfig.setBlockWhenExhausted(true);
 		aConfig.setMaxTotal(config.getMaxTotalCount());
-		aConfig.setMaxWaitMillis(config.getMaxWaitTime());
+		aConfig.setMaxWait(nonNullElse(config.getAllocationTimeout(), DISABLE_DURATION));
 		aConfig.setMinIdle(config.getMinIdleCount());
 		aConfig.setMaxIdle(config.getMaxIdleCount());
-		aConfig.setMinEvictableIdleTimeMillis(0);
-		aConfig.setSoftMinEvictableIdleTimeMillis(config.getMinIdleTime());
-		aConfig.setTimeBetweenEvictionRunsMillis(5000);
+		aConfig.setMinEvictableIdleTime(Duration.ZERO);
+		aConfig.setSoftMinEvictableIdleTime(config.getAutoEvictionMinIdleTime());
+		aConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(5));
 		aConfig.setNumTestsPerEvictionRun(-4);
-		aConfig.setEvictorShutdownTimeoutMillis(0);
+		aConfig.setEvictorShutdownTimeout(Duration.ZERO);
 		
 		return aConfig;
 	}
@@ -165,7 +172,7 @@
 		throw new UnsupportedOperationException();
 	}
 	
-	public void close(final long evictionTimeout) {
+	public void close(final @Nullable Duration evictionTimeout) {
 		synchronized (this.stateLock) {
 			if (this.state > CLOSING) {
 				return;
@@ -173,7 +180,7 @@
 			this.state= CLOSING;
 		}
 		final long evictNanos= APool2NodeHandler.evictNanos(evictionTimeout);
-		final boolean evictDirect= (evictionTimeout == 0);
+		final boolean evictDirect= (evictionTimeout == null);
 		
 		try {
 			Thread.sleep(10);
@@ -191,7 +198,12 @@
 			return;
 		}
 		setNumTestsPerEvictionRun(512);
-		setTimeBetweenEvictionRunsMillis(500);
+		setTimeBetweenEvictionRuns(Duration.ofMillis(500));
+	}
+	
+	@Deprecated(since= "4.5")
+	public void close(final long evictionTimeout) {
+		close((evictionTimeout == 0) ? null : Duration.ofMillis(evictionTimeout));
 	}
 	
 	protected void closeFinally() {
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java
index fe664e8..9618fb4 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java
@@ -16,6 +16,8 @@
 
 import java.rmi.Remote;
 import java.rmi.RemoteException;
+import java.time.Duration;
+import java.time.Instant;
 
 import org.apache.commons.pool2.PooledObject;
 import org.apache.commons.pool2.PooledObjectState;
@@ -37,10 +39,10 @@
 		return (nanos != 0) ? nanos : 1;
 	}
 	
-	static final long evictNanos(final long timeoutMillis) {
+	static final long evictNanos(final @Nullable Duration timeout) {
 		long nanos= System.nanoTime();
-		if (timeoutMillis > 0) {
-			nanos+= timeoutMillis * 1_000_000L;
+		if (timeout != null && !timeout.isNegative()) {
+			nanos+= timeout.toNanos();
 		}
 		return safeNanos(nanos);
 	}
@@ -76,8 +78,8 @@
 	}
 	
 	@Override
-	public long getCreationTime() {
-		return this.p.getCreateTime();
+	public Instant getCreationTime() {
+		return this.p.getCreateInstant();
 	}
 	
 	@Override
@@ -86,8 +88,8 @@
 	}
 	
 	@Override
-	public long getLastestAllocationDuration() {
-		return this.p.getActiveTimeMillis();
+	public @Nullable Duration getLastestAllocationDuration() {
+		return this.p.getActiveDuration();
 	}
 	
 	@Override
@@ -109,7 +111,8 @@
 	}
 	
 	@Override
-	public long getStateTime() {
+	@SuppressWarnings("null")
+	public Instant getStateTime() {
 		switch (getState()) {
 		case DISPOSED:
 			return getShutdownTime();
@@ -143,8 +146,8 @@
 	}
 	
 	@Override
-	public void evict(final long timeout) {
-		doEvict(evictNanos(timeout), timeout == 0);
+	public void evict(final @Nullable Duration timeout) {
+		doEvict(evictNanos(timeout), timeout == null);
 	}
 	
 	void doEvict(final long nanos, final boolean direct) {
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeObject.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeObject.java
index 1a83fdd..c708e90 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeObject.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeObject.java
@@ -14,11 +14,13 @@
 
 package org.eclipse.statet.internal.rj.servi;
 
-import java.util.concurrent.TimeUnit;
+import java.time.Duration;
+import java.time.Instant;
 
 import org.apache.commons.pool2.impl.DefaultPooledObject;
 
 import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
 
 
 @NonNullByDefault
@@ -28,12 +30,12 @@
 	private volatile long lastAllocatedBeginNanos;
 	private volatile long lastAllocatedEndNanos;
 	
-	private volatile long stateTime;
+	private volatile Instant stateTime;
 	
 	
 	public APool2NodeObject(final APool2NodeHandler object) {
 		super(object);
-		this.stateTime= getCreateTime();
+		this.stateTime= getCreateInstant();
 	}
 	
 	
@@ -41,7 +43,7 @@
 	public synchronized boolean allocate() {
 		if (super.allocate()) {
 			this.lastAllocatedBeginNanos= System.nanoTime();
-			this.stateTime= System.currentTimeMillis();
+			this.stateTime= Instant.now();
 			return true;
 		}
 		return false;
@@ -56,7 +58,7 @@
 			this.lastAllocatedEndNanos= System.nanoTime();
 			//$FALL-THROUGH$
 		default:
-			this.stateTime= System.currentTimeMillis();
+			this.stateTime= Instant.now();
 			super.markReturning();
 			return;
 		}
@@ -71,7 +73,7 @@
 			this.lastAllocatedEndNanos= System.nanoTime();
 			//$FALL-THROUGH$
 		case RETURNING:
-			this.stateTime= System.currentTimeMillis();
+			this.stateTime= Instant.now();
 			return super.deallocate();
 		default:
 			return false;
@@ -87,21 +89,21 @@
 			this.lastAllocatedEndNanos= System.nanoTime();
 			//$FALL-THROUGH$
 		default:
-			this.stateTime= System.currentTimeMillis();
+			this.stateTime= Instant.now();
 			super.invalidate();
 			return;
 		}
 	}
 	
 	
-	public long getStateTime() {
+	public Instant getStateTime() {
 		return this.stateTime;
 	}
 	
 	@Override
-	public long getActiveTimeMillis() {
+	public @Nullable Duration getActiveDuration() {
 		if (getBorrowedCount() <= 0) {
-			return -1;
+			return null;
 		}
 		final long end= this.lastAllocatedEndNanos;
 		final long begin= this.lastAllocatedBeginNanos;
@@ -109,7 +111,13 @@
 		if (t < 0) {
 			t= System.nanoTime() - begin;
 		}
-		return TimeUnit.NANOSECONDS.toMillis(t);
+		return Duration.ofNanos(t);
+	}
+	
+	@Override
+	public long getActiveTimeMillis() {
+		final var duration= getActiveDuration();
+		return (duration != null) ? duration.toMillis() : -1;
 	}
 	
 }
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNode.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNode.java
index 09856f4..a5d4482 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNode.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNode.java
@@ -17,7 +17,8 @@
 import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
 
 import java.lang.management.ManagementFactory;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
 
 import javax.management.JMException;
 import javax.management.ObjectName;
@@ -43,7 +44,7 @@
 	private final PoolServer server;
 	private final PoolNodeObject nodeObj;
 	private final RMIAddress address;
-	private final Date creationTime;
+	private final Instant creationTime;
 	
 	private @Nullable ObjectName jmName;
 	
@@ -53,7 +54,7 @@
 		this.nodeObj= nodeObj;
 		final NodeHandler nodeHandler= nonNullAssert(this.nodeObj.getNodeHandler());
 		this.address= nonNullAssert(nodeHandler.getAddress());
-		this.creationTime= new Date(this.nodeObj.getCreationTime());
+		this.creationTime= this.nodeObj.getCreationTime();
 	}
 	
 	
@@ -78,13 +79,13 @@
 	}
 	
 	@Override
-	public Date getCreationTime() {
+	public Instant getCreationTime() {
 		return this.creationTime;
 	}
 	
 	@Override
 	public NodeStateMX getState() {
-		final PoolNodeItem item= new PoolNodeItem(this.nodeObj, System.currentTimeMillis());
+		final PoolNodeItem item= new PoolNodeItem(this.nodeObj, Instant.now());
 		return new MXNodeState(item);
 	}
 	
@@ -125,12 +126,12 @@
 		if (timeoutMillis < 0) {
 			throw new OperationsException("Invalid parameter 'timeoutMillis' >= 0.");
 		}
-		this.nodeObj.evict(timeoutMillis);
+		this.nodeObj.evict(Duration.ofMillis(timeoutMillis));
 	}
 	
 	@Override
 	public void kill() throws OperationsException {
-		this.nodeObj.evict(0);
+		this.nodeObj.evict(null);
 	}
 	
 }
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeConfig.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeConfig.java
index 86e195a..2eedbe9 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeConfig.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeConfig.java
@@ -17,6 +17,7 @@
 import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
 
 import java.lang.management.ManagementFactory;
+import java.time.Duration;
 import java.util.Map;
 
 import javax.management.JMException;
@@ -74,6 +75,19 @@
 	
 	
 	@Override
+	public long getStartStopTimeoutMillis() {
+		final var timeout= getStartStopTimeout();
+		return (timeout != null) ? timeout.toMillis() : -1;
+	}
+	
+	@Override
+	public void setStartStopTimeoutMillis(final long milliseconds) {
+		final var duration= (milliseconds != -1) ? Duration.ofMillis(milliseconds) : null;
+		setStartStopTimeout(duration);
+	}
+	
+	
+	@Override
 	public void apply() throws OperationsException {
 		synchronized (this) {
 			MXUtils.validate(this);
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeState.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeState.java
index 979e62e..91a28b0 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeState.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXNodeState.java
@@ -14,6 +14,7 @@
 
 package org.eclipse.statet.internal.rj.servi;
 
+import java.time.Instant;
 import java.util.Date;
 
 import org.eclipse.statet.jcommons.lang.NonNullByDefault;
@@ -31,15 +32,15 @@
 	
 	private final PoolNodeItem item;
 	
-	private final Date creationTime;
-	private final Date stateTime;
+	private final Instant creationTime;
+	private final Instant stateTime;
 	
 	
 	public MXNodeState(final PoolNodeItem item) {
 		this.item= item;
 		
-		this.creationTime= new Date(this.item.getCreationTime());
-		this.stateTime= new Date(this.item.getStateTime());
+		this.creationTime= this.item.getCreationTime();
+		this.stateTime= this.item.getStateTime();
 	}
 	
 	
@@ -50,7 +51,7 @@
 	
 	@Override
 	public Date getStateBeginTime() {
-		return this.stateTime;
+		return Date.from(this.stateTime);
 	}
 	
 	@Override
@@ -61,7 +62,7 @@
 	
 	@Override
 	public Date getCreationTime() {
-		return this.creationTime;
+		return Date.from(this.creationTime);
 	}
 	
 	@Override
@@ -70,8 +71,9 @@
 	}
 	
 	@Override
-	public long getUsageDuration() {
-		return this.item.getUsageDuration();
+	public long getUsageDurationMillis() {
+		final var duration= this.item.getUsageDuration();
+		return (duration != null) ? duration.toMillis() : -1;
 	}
 	
 	@Override
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolConfig.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolConfig.java
index 8de2b06..50c1a8b 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolConfig.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolConfig.java
@@ -17,6 +17,7 @@
 import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
 
 import java.lang.management.ManagementFactory;
+import java.time.Duration;
 
 import javax.management.JMException;
 import javax.management.ObjectName;
@@ -88,4 +89,40 @@
 		MXUtils.save(this, this.server.getRJContext());
 	}
 	
+	
+	@Override
+	public long getAutoEvictionMinIdleTimeMillis() {
+		final var duration= getAutoEvictionMinIdleTime();
+		return duration.toMillis();
+	}
+	
+	@Override
+	public void setAutoEvictionMinIdleTimeMillis(final long milliseconds) {
+		setAutoEvictionMinIdleTime(Duration.ofMillis(milliseconds));
+	}
+	
+	@Override
+	public long getAllocationTimeoutMillis() {
+		final var duration= getAllocationTimeout();
+		return (duration != null) ? duration.toMillis() : -1;
+	}
+	
+	@Override
+	public void setAllocationTimeoutMillis(final long milliseconds) {
+		final var duration= (milliseconds != -1) ? Duration.ofMillis(milliseconds) : null;
+		setAllocationTimeout(duration);
+	}
+	
+	@Override
+	public long getEvictionTimeoutMillis() {
+		final var duration= getEvictionTimeout();
+		return duration.toMillis();
+	}
+	
+	@Override
+	public void setEvictionTimeoutMillis(final long milliseconds) {
+		setEvictionTimeout(Duration.ofMillis(milliseconds));
+	}
+	
+	
 }
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolStatus.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolStatus.java
index c700dfd..0e7591a 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolStatus.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/MXPoolStatus.java
@@ -17,6 +17,7 @@
 import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullLateInit;
 
 import java.lang.management.ManagementFactory;
+import java.time.Instant;
 import java.util.Date;
 
 import javax.management.JMException;
@@ -38,7 +39,7 @@
 	
 	private @Nullable ObjectName jmName;
 	
-	private Date time= nonNullLateInit(); // ::refresh
+	private Instant time= nonNullLateInit(); // ::refresh
 	
 	
 	public MXPoolStatus(final PoolServer server) {
@@ -63,9 +64,9 @@
 	}
 	
 	protected synchronized void refresh() {
-		final long stamp= System.currentTimeMillis();
+		final Instant stamp= Instant.now();
 		refresh(this.server.getManager(), stamp);
-		this.time= new Date(stamp);
+		this.time= stamp;
 	}
 	
 	
@@ -77,7 +78,7 @@
 	
 	@Override
 	public synchronized Date getStatusTime() {
-		return this.time;
+		return Date.from(this.time);
 	}
 	
 	
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeConfigMXBean.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeConfigMXBean.java
index e704ba5..d98a43e 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeConfigMXBean.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeConfigMXBean.java
@@ -55,9 +55,9 @@
 	String getRStartupSnippet();
 	void setRStartupSnippet(@Nullable String code);
 	
-	@DisplayName("Timeout when starting/stopping node (millis)")
-	long getStartStopTimeout();
-	void setStartStopTimeout(long milliseconds);
+	@DisplayName("Timeout when starting/stopping node (millisec)")
+	long getStartStopTimeoutMillis();
+	void setStartStopTimeoutMillis(long milliseconds);
 	
 	@DisplayName("Enable debug console")
 	boolean getEnableConsole();
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeMXBean.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeMXBean.java
index e33a78c..119d34b 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeMXBean.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeMXBean.java
@@ -14,7 +14,7 @@
 
 package org.eclipse.statet.rj.servi.jmx;
 
-import java.util.Date;
+import java.time.Instant;
 
 import javax.management.OperationsException;
 
@@ -26,7 +26,12 @@
 	
 	
 	String getId();
-	Date getCreationTime();
+	
+	/**
+	 * @since 4.5
+	 */
+	Instant getCreationTime();
+	
 	
 	NodeStateMX getState();
 	
@@ -36,9 +41,9 @@
 	
 	@DisplayName("Stop using the default timeout")
 	void stop() throws OperationsException;
-	@DisplayName("Stop using given timeout")
+	@DisplayName("Stop using given timeout (millisec)")
 	void stop(long timeoutMillis) throws OperationsException;
-	@DisplayName("Stop using timeout 0")
+	@DisplayName("Stop directly")
 	void kill() throws OperationsException;
 	
 }
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeStateMX.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeStateMX.java
index 2f4d535..399d46d 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeStateMX.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/NodeStateMX.java
@@ -28,15 +28,18 @@
 	
 	Date getCreationTime();
 	
+	
 	PoolNodeState getState();
 	
 	Date getStateBeginTime();
 	
 	@Nullable String getCurrentClientLabel();
 	
+	
 	long getUsageCount();
 	
-	long getUsageDuration();
+	long getUsageDurationMillis();
+	
 	
 	@Nullable String getRMIAddress();
 	
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/PoolConfigMXBean.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/PoolConfigMXBean.java
index 16980a0..b6ab0e1 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/PoolConfigMXBean.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/jmx/PoolConfigMXBean.java
@@ -24,32 +24,32 @@
 	
 	
 	@DisplayName("Max total nodes (count)")
-	int getMaxUsageCount();
-	void setMaxUsageCount(int count);
-	
-	@DisplayName("Min idle nodes (count)")
-	long getMaxWaitTime();
-	void setMaxWaitTime(long milliseconds);
-	
-	@DisplayName("Max idle nodes (count)")
-	long getMinIdleTime();
-	void setMinIdleTime(long milliseconds);
-	
-	@DisplayName("Min node idle time (millisec)")
-	int getMaxIdleCount();
-	void setMaxIdleCount(int count);
-	
-	@DisplayName("Max wait time (millisec)")
-	int getMinIdleCount();
-	void setMinIdleCount(int count);
-	
-	@DisplayName("Max node reuse (count)")
 	int getMaxTotalCount();
 	void setMaxTotalCount(int count);
 	
+	@DisplayName("Max idle nodes (count)")
+	int getMaxIdleCount();
+	void setMaxIdleCount(int count);
+	
+	@DisplayName("Min idle nodes (count)")
+	int getMinIdleCount();
+	void setMinIdleCount(int count);
+	
+	@DisplayName("Max reuse of node (count)")
+	int getMaxUsageCount();
+	void setMaxUsageCount(int count);
+	
+	@DisplayName("Min idle duration of node before automatic eviction (millisec)")
+	long getAutoEvictionMinIdleTimeMillis();
+	void setAutoEvictionMinIdleTimeMillis(long milliseconds);
+	
+	@DisplayName("Timeout when requesting node (millisec)")
+	long getAllocationTimeoutMillis();
+	void setAllocationTimeoutMillis(long milliseconds);
+	
 	@DisplayName("Timeout when evicting node in use (millisec)")
-	long getEvictionTimeout();
-	void setEvictionTimeout(long milliseconds);
+	long getEvictionTimeoutMillis();
+	void setEvictionTimeoutMillis(long milliseconds);
 	
 	
 	@DisplayName("Apply the current configuration")
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolConfig.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolConfig.java
index 2931e6c..f4483a9 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolConfig.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolConfig.java
@@ -14,6 +14,11 @@
 
 package org.eclipse.statet.rj.servi.pool;
 
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
+import static org.eclipse.statet.internal.rj.servi.Utils.isNegative;
+
+import java.time.Duration;
 import java.util.Collection;
 import java.util.Properties;
 
@@ -57,28 +62,28 @@
 	 */
 	public static final String EVICT_TIMEOUT_ID= "eviction_timeout.millis";
 	
-	private static final long EVICT_TIMEOUT_DEFAULT= 30*MINUTES;
+	private static final Duration EVICT_TIMEOUT_DEFAULT= Duration.ofMinutes(30);
 	
 	
 	private int maxTotalCount;
 	private int minIdleCount;
 	private int maxIdleCount;
-	private long minIdleTime;
-	private long maxWaitTime;
+	private Duration autoEvictionMinIdleTime;
 	private int maxUsageCount;
 	
-	private long evictTimeout;
+	private @Nullable Duration allocationTimeout;
+	private Duration evictionTimeout;
 	
 	
 	public PoolConfig() {
 		this.maxTotalCount= 20;
 		this.minIdleCount= 1;
 		this.maxIdleCount= 10;
-		this.minIdleTime= 10*MINUTES;
-		this.maxWaitTime= 3*SECONDS;
+		this.autoEvictionMinIdleTime= Duration.ofMinutes(10);
 		this.maxUsageCount= 1000;
+		this.allocationTimeout= Duration.ofSeconds(3);
 		
-		this.evictTimeout= EVICT_TIMEOUT_DEFAULT;
+		this.evictionTimeout= EVICT_TIMEOUT_DEFAULT;
 	}
 	
 	public PoolConfig(final PoolConfig config) {
@@ -98,23 +103,29 @@
 		this.maxTotalCount= templ.maxTotalCount;
 		this.minIdleCount= templ.minIdleCount;
 		this.maxIdleCount= templ.maxIdleCount;
-		this.minIdleTime= templ.minIdleTime;
-		this.maxWaitTime= templ.maxWaitTime;
+		this.autoEvictionMinIdleTime= templ.autoEvictionMinIdleTime;
+		this.allocationTimeout= templ.allocationTimeout;
 		this.maxUsageCount= templ.maxUsageCount;
-		this.evictTimeout= templ.evictTimeout;
+		this.evictionTimeout= templ.evictionTimeout;
 	}
 	
 	@Override
 	public synchronized void load(final Properties map) {
-		this.maxTotalCount= Integer.parseInt(map.getProperty(MAX_TOTAL_COUNT_ID));
-		this.minIdleCount= Integer.parseInt(map.getProperty(MIN_IDLE_COUNT_ID));
-		this.maxIdleCount= Integer.parseInt(map.getProperty(MAX_IDLE_COUNT_ID));
-		this.minIdleTime= Long.parseLong(Utils.getProperty(map, MIN_IDLE_MILLIS_ID, MIN_IDLE_TIME_ID));
-		this.maxWaitTime= Long.parseLong(Utils.getProperty(map, MAX_WAIT_MILLIS_ID, MAX_WAIT_TIME_ID));
-		this.maxUsageCount= Integer.parseInt(map.getProperty(MAX_USAGE_COUNT_ID));
-		{	final String s= map.getProperty(EVICT_TIMEOUT_ID);
-			this.evictTimeout= (s != null) ? Long.parseLong(s) : EVICT_TIMEOUT_DEFAULT;
-		}
+		this.maxTotalCount= Integer.parseInt(
+				map.getProperty(MAX_TOTAL_COUNT_ID) );
+		this.minIdleCount= Integer.parseInt(
+				map.getProperty(MIN_IDLE_COUNT_ID) );
+		this.maxIdleCount= Integer.parseInt(
+				map.getProperty(MAX_IDLE_COUNT_ID) );
+		this.autoEvictionMinIdleTime= Utils.parseDuration(
+				Utils.getProperty(map, MIN_IDLE_MILLIS_ID, MIN_IDLE_TIME_ID) );
+		this.allocationTimeout= Utils.parseNullableDuration(
+				Utils.getProperty(map, MAX_WAIT_MILLIS_ID, MAX_WAIT_TIME_ID) );
+		this.maxUsageCount= Integer.parseInt(
+				map.getProperty(MAX_USAGE_COUNT_ID) );
+		this.evictionTimeout= Utils.parseDuration(
+				map.getProperty(EVICT_TIMEOUT_ID),
+				EVICT_TIMEOUT_DEFAULT );
 	}
 	
 	@Override
@@ -122,10 +133,10 @@
 		map.setProperty(MAX_TOTAL_COUNT_ID, Integer.toString(this.maxTotalCount));
 		map.setProperty(MIN_IDLE_COUNT_ID, Integer.toString(this.minIdleCount));
 		map.setProperty(MAX_IDLE_COUNT_ID, Integer.toString(this.maxIdleCount));
-		map.setProperty(MIN_IDLE_MILLIS_ID, Long.toString(this.minIdleTime));
-		map.setProperty(MAX_WAIT_MILLIS_ID, Long.toString(this.maxWaitTime));
+		map.setProperty(MIN_IDLE_MILLIS_ID, Utils.serDuration(this.autoEvictionMinIdleTime));
+		map.setProperty(MAX_WAIT_MILLIS_ID, Utils.serNullableDuration(this.allocationTimeout));
 		map.setProperty(MAX_USAGE_COUNT_ID, Integer.toString(this.maxUsageCount));
-		map.setProperty(EVICT_TIMEOUT_ID, Long.toString(this.evictTimeout));
+		map.setProperty(EVICT_TIMEOUT_ID, Utils.serDuration(this.evictionTimeout));
 	}
 	
 	public synchronized int getMaxTotalCount() {
@@ -152,52 +163,62 @@
 		this.maxIdleCount= count;
 	}
 	
-	public synchronized long getMinIdleTime() {
-		return this.minIdleTime;
+	/**
+	 * @since 4.5
+	 */
+	public synchronized Duration getAutoEvictionMinIdleTime() {
+		return this.autoEvictionMinIdleTime;
 	}
 	
-	public synchronized void setMinIdleTime(final long milliseconds) {
-		this.minIdleTime= milliseconds;
-	}
-	
-	public synchronized void setMaxWaitTime(final long milliseconds) {
-		this.maxWaitTime= milliseconds;
-	}
-	
-	public synchronized long getMaxWaitTime() {
-		return this.maxWaitTime;
-	}
-	
-	public synchronized void setMaxUsageCount(final int count) {
-		this.maxUsageCount= count;
+	/**
+	 * @since 4.5
+	 */
+	public synchronized void setAutoEvictionMinIdleTime(final Duration duration) {
+		this.autoEvictionMinIdleTime= nonNullAssert(duration);
 	}
 	
 	public synchronized int getMaxUsageCount() {
 		return this.maxUsageCount;
 	}
 	
+	public synchronized void setMaxUsageCount(final int count) {
+		this.maxUsageCount= count;
+	}
+	
+	/**
+	 * @since 4.5
+	 */
+	public synchronized @Nullable Duration getAllocationTimeout() {
+		return this.allocationTimeout;
+	}
+	
+	/**
+	 * @since 4.5
+	 */
+	public synchronized void setAllocationTimeout(final @Nullable Duration timeout) {
+		this.allocationTimeout= timeout;
+	}
 	
 	/**
 	 * Returns the timeout when evicing lent pool items
 	 * 
-	 * @return the timeout in milliseconds
+	 * @return the timeout
 	 * 
-	 * @since 2.0
+	 * @since 4.5
 	 */
-	public synchronized long getEvictionTimeout() {
-		return this.evictTimeout;
+	public synchronized Duration getEvictionTimeout() {
+		return this.evictionTimeout;
 	}
 	
 	/**
 	 * Sets the timeout when evicing lent pool items
 	 * 
-	 * @param milliseconds the timeout in milliseconds
+	 * @param duration the timeout
 	 * 
-	 * @since 2.0
+	 * @since 4.5
 	 */
-	
-	public synchronized void setEvictionTimeout(final long milliseconds) {
-		this.evictTimeout= milliseconds;
+	public synchronized void setEvictionTimeout(final Duration duration) {
+		this.evictionTimeout= nonNullAssert(duration);
 	}
 	
 	
@@ -229,15 +250,15 @@
 			}
 			valid= false;
 		}
-		if (this.minIdleTime < 0L) {
+		if (this.autoEvictionMinIdleTime.isNegative()) {
 			if (messages != null) {
 				messages.add(new ValidationMessage(MIN_IDLE_MILLIS_ID, "Value must be >= 0"));
 			}
 			valid= false;
 		}
-		if (this.maxWaitTime < 0L && this.maxUsageCount != -1) {
+		if (this.maxUsageCount != -1 && isNegative(this.allocationTimeout)) {
 			if (messages != null) {
-				messages.add(new ValidationMessage(MAX_WAIT_MILLIS_ID, "Value must be >= 0 or == -1 (infinite)"));
+				messages.add(new ValidationMessage(MAX_WAIT_MILLIS_ID, "Value must be >= 0 or unset/== -1 (infinite)"));
 			}
 			valid= false;
 		}
@@ -248,7 +269,7 @@
 			valid= false;
 		}
 		
-		if (this.evictTimeout < 0) {
+		if (this.evictionTimeout.isNegative()) {
 			if (messages != null) {
 				messages.add(new ValidationMessage(EVICT_TIMEOUT_ID, "Value must be >= 0"));
 			}
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeItem.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeItem.java
index c79357f..1278c12 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeItem.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeItem.java
@@ -14,6 +14,9 @@
 
 package org.eclipse.statet.rj.servi.pool;
 
+import java.time.Duration;
+import java.time.Instant;
+
 import org.eclipse.statet.jcommons.lang.NonNullByDefault;
 import org.eclipse.statet.jcommons.lang.Nullable;
 import org.eclipse.statet.jcommons.rmi.RMIAddress;
@@ -28,19 +31,19 @@
 	
 	private final PoolNodeObject nodeObj;
 	
-	private long creationTime;
+	private Instant creationTime;
 	
 	private PoolNodeState state;
-	private long stateTime;
+	private Instant stateTime;
 	
 	private long usageCount;
-	private long usageDuration;
+	private @Nullable Duration usageDuration;
 	
 	private @Nullable RMIAddress address;
 	private @Nullable String clientLabel;
 	
 	
-	public PoolNodeItem(final PoolNodeObject nodeObj, final long stamp) {
+	public PoolNodeItem(final PoolNodeObject nodeObj, final Instant stamp) {
 		synchronized(nodeObj) {
 			this.nodeObj= nodeObj;
 			
@@ -58,7 +61,10 @@
 	}
 	
 	
-	public long getCreationTime() {
+	/**
+	 * @since 4.5
+	 */
+	public Instant getCreationTime() {
 		return this.creationTime;
 	}
 	
@@ -66,7 +72,10 @@
 		return this.state;
 	}
 	
-	public long getStateTime() {
+	/**
+	 * @since 4.5
+	 */
+	public Instant getStateTime() {
 		return this.stateTime;
 	}
 	
@@ -78,7 +87,10 @@
 		return this.usageCount;
 	}
 	
-	public long getUsageDuration() {
+	/**
+	 * @since 4.5
+	 */
+	public @Nullable Duration getUsageDuration() {
 		return this.usageDuration;
 	}
 	
@@ -117,13 +129,13 @@
 	 * 
 	 * The specified timeout is used when the node is in use.
 	 * 
-	 * @param timeoutMillis the timeout in milliseconds
+	 * @param timeout the timeout
 	 * 
-	 * @since 2.0
+	 * @since 4.5
 	 */
-	public void evict(final long timeoutMillis) {
+	public void evict(final @Nullable Duration timeout) {
 		if (this.nodeObj != null) {
-			this.nodeObj.evict(timeoutMillis);
+			this.nodeObj.evict(timeout);
 		}
 	}
 	
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeObject.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeObject.java
index 5ad5b75..a7e04bc 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeObject.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolNodeObject.java
@@ -14,6 +14,9 @@
 
 package org.eclipse.statet.rj.servi.pool;
 
+import java.time.Duration;
+import java.time.Instant;
+
 import org.eclipse.statet.jcommons.lang.NonNullByDefault;
 import org.eclipse.statet.jcommons.lang.Nullable;
 
@@ -30,8 +33,10 @@
 	 * Returns the time of the creation of the node.
 	 * 
 	 * @return the time in milliseconds (as specified by {@link System#currentTimeMillis()})
+	 * 
+	 * @since 4.5
 	 */
-	long getCreationTime();
+	Instant getCreationTime();
 	
 	/**
 	 * Returns the count of allocation of this node.
@@ -49,9 +54,11 @@
 	 * If the node is currently allocated, it is the duration of the current allocation at this
 	 * time.
 	 * 
-	 * @return the duration in milliseconds, or {@code -1} if not available
+	 * @return the duration, or {@code null} if not available
+	 * 
+	 * @since 4.5
 	 */
-	long getLastestAllocationDuration();
+	@Nullable Duration getLastestAllocationDuration();
 	
 	/**
 	 * Returns the current state.
@@ -60,11 +67,27 @@
 	 */
 	PoolNodeState getState();
 	
-	long getStateTime();
+	/**
+	 * @since 4.5
+	 */
+	Instant getStateTime();
 	
 	@Nullable String getClientLabel();
 	
-	void evict(long timeoutMillis);
+	/**
+	 * Marks this node for eviction.
+	 * 
+	 * @param timeout the timeout for eviction, or {@code null} for direct eviction in current
+	 *     thread
+	 * 
+	 * @since 4.5
+	 */
+	void evict(@Nullable Duration timeout);
+	
+	@Deprecated(since= "4.5")
+	default void evict(final long timeoutMillis) {
+		evict((timeoutMillis == 0) ? null : Duration.ofMillis(timeoutMillis));
+	}
 	
 	
 }
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolStatus.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolStatus.java
index 41eef1d..1abb59a 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolStatus.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/rj/servi/pool/PoolStatus.java
@@ -17,6 +17,7 @@
 import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
 import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullLateInit;
 
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -43,7 +44,7 @@
 	protected final PoolServer server;
 	
 	/*-- init in ::check() --*/
-	private long stamp;
+	private Instant stamp= nonNullLateInit();
 	private RServiPoolManager.Counter counter= nonNullLateInit();
 	private List<N> nodeStates= nonNullLateInit();
 	
@@ -53,7 +54,10 @@
 	}
 	
 	
-	protected long getStatusStamp() {
+	/**
+	 * @since 4.5
+	 */
+	protected Instant getStatusStamp() {
 		return this.stamp;
 	}
 	
@@ -98,7 +102,7 @@
 	}
 	
 	
-	protected void refresh(final @Nullable RServiPoolManager manager, final long stamp) {
+	protected void refresh(final @Nullable RServiPoolManager manager, final Instant stamp) {
 		final List<N> list;
 		RServiPoolManager.Counter counter;
 		
@@ -136,7 +140,7 @@
 		this.nodeStates= list;
 	}
 	
-	protected PoolNodeItem createPoolItem(final PoolNodeObject node, final long stamp) {
+	protected PoolNodeItem createPoolItem(final PoolNodeObject node, final Instant stamp) {
 		return new PoolNodeItem(node, stamp);
 	}