使用JNA设置系统时间

 最近做项目需要实现时钟同步的功能, 对于NTP协议有现成的开源库很容易实现, 但是设置系统时间JAVA本身并不支持, 看来只能访问系统库了. 把我的研究心得给大家分享.

    java是跨平台的, 所以访问系统库也要尽可能的跨平台了. 最初我希望通过调用标准C函数来实现跨平台, 实验了之后发现标准C函数只支持到秒级, 而时钟同步精度至少要到毫秒级, 很失望. 只好再找去它方法, 后来想到kernel32.dll应该是所有windows系统都有的库, 而libc.so是所有linux系统都有的库, 恩, 看来只能用这种方法来分别处理了, 也算是跨平台了.

1. 环境

     jdk1.6

     windows xp

     openSUSE11.2

2. 依赖的jar

   本程序需要依赖JNA框架.

   jna.jar

3. 接口

import java.util.Date;

public interface JNative {

    /**
     * 设置系统时间
     * @param date Date
     */
    public void setLocalTime(Date date);
   
}

 

4. windows实现



import java.util.Calendar;
import java.util.Date;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;

public class WindowsImpl implements JNative{

    public static class SYSTEMTIME extends Structure {
        public short wYear;
        public short wMonth;
        public short wDayOfWeek;
        public short wDay;
        public short wHour;
        public short wMinute;
        public short wSecond;
        public short wMilliseconds;
    }
   
    public interface Kernel32 extends Library{
       
        public boolean SetLocalTime(SYSTEMTIME st); //带时区
        public int GetCurrentProcessId();
       
    }
   
    public static Kernel32 kernel32Instance = null;
   
    public WindowsImpl(){
        kernel32Instance = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
    }
   
    @Override
    public void setLocalTime(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
       
        SYSTEMTIME st = new SYSTEMTIME();
        st.wYear = (short)c.get(Calendar.YEAR);
        st.wMonth = (short)(c.get(Calendar.MONTH) + 1);
        st.wDay = (short)c.get(Calendar.DAY_OF_MONTH );
        st.wDayOfWeek = (short)c.get(Calendar.DAY_OF_WEEK);
        st.wHour = (short)c.get(Calendar.HOUR_OF_DAY);
        st.wMinute = (short)c.get(Calendar.MINUTE);
        st.wSecond = (short)c.get(Calendar.SECOND);
        st.wMilliseconds = (short)c.get(Calendar.MILLISECOND);
       
        kernel32Instance.SetLocalTime(st);
    }

}

 

5. linux实现



import java.util.Date;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Structure;

public class LinuxImpl implements JNative {

    public static class tm extends Structure{
       
        public static class ByReference extends tm implements Structure.ByReference{}
        public static class ByValue extends tm implements Structure.ByValue{}
       
        public int tm_sec;//seconds 0-61
        public int tm_min;//minutes 1-59
        public int tm_hour;//hours 0-23
        public int tm_mday;//day of the month 1-31
        public int tm_mon;//months since jan 0-11
        public int tm_year;//years from 1900
        public int tm_wday;//days since Sunday, 0-6
        public int tm_yday;//days since Jan 1, 0-365
        public int tm_isdst;//Daylight Saving time indicator
    }
    public static class timeval extends Structure{
        public static class ByReference extends timeval implements Structure.ByReference{}
        public static class ByValue extends timeval implements Structure.ByValue{}
       
        public NativeLong tv_sec; /* 秒数 */
        public NativeLong tv_usec; /* 微秒数 */
    }
    public static class timezone extends Structure{
        public static class ByReference extends timezone implements Structure.ByReference{}
        public static class ByValue extends timezone implements Structure.ByValue{}
       
        public int tz_minuteswest;
        public int tz_dsttime;
    }
   
    public interface CLibrary extends Library{
       
        int gettimeofday(timeval.ByReference tv, timezone.ByReference tz);
        int settimeofday(timeval.ByReference tv, timezone.ByReference tz);
       
    }
   
    public static CLibrary cLibraryInstance = null;
   
    public LinuxImpl(){
        cLibraryInstance = (CLibrary)Native.loadLibrary("c", CLibrary.class);
    }
   
    @Override
    public void setLocalTime(Date date) {
        long ms = date.getTime();
       
        long s = ms / 1000; //秒
        long us = (ms % 1000) * 1000; //微秒
       
        timeval.ByReference tv = new timeval.ByReference();
        timezone.ByReference tz = new  timezone.ByReference();
        cLibraryInstance.gettimeofday(tv, tz);
       
        tv.tv_sec = new NativeLong(s);
        tv.tv_usec = new NativeLong(us);
        cLibraryInstance.settimeofday(tv, tz);
    }

}

 

6. 工厂类



import com.sun.jna.Platform;

public class NativeFactory {
   
    public static JNative newNative(){
        if(Platform.isWindows()){
            return new WindowsImpl();
        }
       
        return new LinuxImpl();
    }

}

 

7. 测试

public static void main(String args[]){
        System.out.println("1. " + new Date());
        JNative jNative = NativeFactory.newNative();
        jNative.setLocalTime(new Date(System.currentTimeMillis() + (10*60*1000))); //10分钟
        System.out.println("2. " + new Date());
    }

 

执行结果是系统时间增加了10分钟, 本程序在windows xp和openSUSE11.2下测试通过.

注意new Date()获取的时间为系统时间, 不是硬件时间.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值