最近做项目需要实现时钟同步的功能, 对于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()获取的时间为系统时间, 不是硬件时间.
分享到:
相关推荐
// 获取系统时间并设置本地时间的代码... } } ``` 这里,我们创建了`Kernel32`接口的实例,并使用`GetLocalTime()`获取了本地时间。然后,可以遍历`SYSTEMTIME`结构体的字段,将时间信息格式化后输出。 5. **...
例如,如果你想要在Java中获取系统时间,可以使用`com.sun.jna.platform.win32Kernel32`类中的`GetSystemTimeAsFileTime()`方法,而在Unix系统中,可以使用`com.sun.jna.platform.unixLibc`类的`time()`方法。这些类...
它支持Windows、Unix、Linux以及Mac OS X等操作系统,并且可以轻松地跨平台使用。 **2. JNA的优势** - **无需C代码**: 使用JNA,开发者无需编写C代码即可调用本地库。 - **简化开发**: JNA提供了一种更加简单和...
例如,通过JNA,你可以轻松地调用Windows API来获取系统时间,或者在Linux上使用POSIX函数进行进程管理。在提供的"娣卞叆娴呭嚭JNA鈥斿揩閫熻皟鐢ㄥ師鐢熷嚱鏁_.0.pdf"教程中,可能会包含具体的示例代码,演示如何...
对于 JFrame 的透明度,JNA 可能被用来调用操作系统级别的 API 来设置窗口属性,比如 Windows 上的 `SetLayeredWindowAttributes` 函数或 X11 系统的 `XSetWindowAttributes` 函数。不规则形状的 JFrame 则可能涉及...
1. **无需JNI**:使用JNA,开发者可以避免编写JNI代码,减少错误和调试时间。 2. **自动类型映射**:JNA可以自动将Java类型映射为本地类型,如int、double、字符串等。 3. **数组和结构体支持**:JNA能够处理数组和...
目前Java没有直接设置系统时间精确到毫秒的方法,这里结合C可以时间。使用Java代码调用C库。
SetLocalTime():设置本地时间。注:此方法需要系统管理员权限。 通过查询知道这些方法都封装在kernel32.dll文件中,下面进行调用。 最后说一下,实在看不贯某些同学,公共的开源资源,赚取大量积分的行为。
下面的例子展示了如何使用JNA获取当前系统时间: ```java import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinBase; ...
- **平台兼容性**:JNA支持多种操作系统,包括Unix、Linux、Windows和Mac OS X。 #### 三、JNA的使用示例 ##### 1. JNA入门 - **准备工作**:首先,需要下载并配置`jna.jar` 和 `example.jar` 文件。 - **环境...
这个库让开发者能够更容易地访问特定于操作系统的功能,例如文件系统、用户管理、网络设置等。在`platform.jar`中,已经封装了大量的常见操作系统函数,减少了开发者自行查找和映射原生API的繁琐工作。 使用Java ...
利用Java代码设置Linux系统时间。设置时间精确到毫秒级别。
Java Native Access(JNA)是Java平台上的一个开源库,它提供了一种简单的方法来调用平台本机库,无需编写JNI(Java ...通过深入理解和熟练使用JNA,Java开发者可以充分利用本地系统的功能,提高应用程序的性能和功能。
5. 实时更新图表数据,可以设置定时器每隔一定时间调用JNA获取新的CPU使用率,并添加到图表中。 这样,你就可以得到一个实时显示CPU使用率的动态曲线图,这对于监控系统性能或分析数据趋势非常有用。注意,确保你的...
JNI适合对性能有严格要求且愿意投入更多时间在本地代码上的项目,而JNA则为开发者提供了便利,牺牲了一定的性能以换取开发效率。在实际应用中,应根据项目需求和团队能力选择合适的方法。无论是JNI还是JNA,它们都极...
2. **调用机制**:JNI使用系统调用直接调用本地函数,而JNA通过Java的反射机制进行调用,反射通常比直接调用慢。 3. **内存管理**:JNI允许直接操作内存,而JNA由Java自动管理内存,这可能导致额外的内存复制和垃圾...
- **避免使用C语言**:JNA最大的优势之一就是它允许开发者直接使用Java代码调用本地系统API,无需编写任何C代码。这极大地简化了开发流程,减少了潜在的错误和问题。 - **减少错误和维护成本**:使用JNI时常见的...
Java并发核心编程是Java开发中的重要领域,它涉及到如何在多线程环境下高效地执行代码...而JNA的使用则为Java与本地系统的交互提供了便利,但也带来了额外的并发挑战,需要开发者具备扎实的并发基础知识才能有效应对。
**Java Native Access (JNA)** 是一个 ...如果你需要与操作系统底层进行交互,或者使用特定的本机库,JNA 可能是一个值得考虑的选择。通过深入学习和实践,你可以掌握 JNA 的使用,提升 Java 应用程序的功能和性能。
注册表是Windows操作系统中的一个重要数据库,存储了系统的配置信息,如软件设置、硬件设备信息等。Java本身并不直接支持读取注册表,但我们可以借助第三方库,比如JNA(Java Native Access)或者Jacob(Java ...