RHEL 5 / RHEL 6上的libfaketime和java

时间:2014-10-28 07:07:58

标签: java linux time rhel

为了测试日期/时间设置为过去或未来的java代码我想尝试libfaketime(目前我们只是调整系统时钟,但它会像非工作的kerberos等那样造成很多麻烦)。

我尝试使用这个小测试程序:

$ cat time.java
import java.util.*;

class TimeTest {

    public static void main(String[] s) {

        long timeInMillis = System.currentTimeMillis();
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(timeInMillis);
        java.util.Date date = cal.getTime();

        System.out.println("Date: " + date);
    }
}

执行此操作:

LD_ASSUME_KERNEL=2.6.18 LD_PRELOAD=/usr/lib64/libfaketime.so.1 FAKETIME="-15d" /opt/IBM/WebSphere/AppServer/java_1.7_64/bin/java TimeTest
Invalid clock_id for clock_gettime: -172402[root@myhost ~]#

但正如您所看到的,我只是收到一条错误消息。 测试在RHEL 6.5服务器,内核2.6.32-431和 libfaketime 0.9.6

您有什么建议我可以解决这个问题吗?我也有兴趣听听你在RHEL上使用libfaketime和java的经历。

我还在https://github.com/wolfcw/libfaketime/issues

报告了此问题

最好的反馈,

二苓

1 个答案:

答案 0 :(得分:0)

我在IBM JVM 1.7.0中也发现了这种不正确的行为,而在Oracle JVM 1.6.0中,这可以按预期工作。 解释是IBM JVM实际上有一个内部错误,通过使用不正确的clock_id参数(随机负值)调用clock_gettime系统调用来表现。 解决方法(不是修复)是修改libfaketime.c以将clock_id重置为fake_clock_gettime函数中的有效值。

case FT_START_AT: /* User-specified offset */
  if (user_per_tick_inc_set)
  {
    /* increment time with every time() call*/
    next_time(tp, &user_per_tick_inc);
  }
  else
  { 
    if (clk_id < 0) { // jvm calls clock_gettime() with invalid random negative clock_id value
        clk_id = CLOCK_REALTIME;
    }

    switch (clk_id)
    // the rest is the same

这将阻止libfaketime.so.1库在您正在观察的错误中存在

 printf("\nInvalid clock_id for clock_gettime: %d", clk_id);
 exit(EXIT_FAILURE);

请注意,这种解决方法有一个缺点,即如果JVM错误地询问系统是否有无效的clockid,我们将假设有效的clockid可能不是应用程序所期望的。