System.currentTimeMillis() verfälschen möglich?

Hallo,

ich soll für die Schule ein kleines Java-Programm schreiben, das unter anderem auch mit System.currentTimeMillis() die aktuelle Zeit abholt und damit Messungen anstellt. Im Auftrag ist auch ganz klar festgehalten, dass das Programm so zu schreiben ist, dass der Benutzer die Zeit nicht irgendwie manipulieren kann.

Meine Frage wäre nun, ob diese Voraussetzung bei System.currentTimeMillis() gegeben ist, sprich, wenn ich am Computer, während das Programm läuft, in den Einstellungen die Uhrzeit ändere, sich dies auch auf System.currentTimeMillies() auswirkt? Falls ja, gibt es eine Möglichkeit, wie ich das verhindern kann?

Ich habe im Moment leider keinen Computer mit genug Rechten zur Hand, um das selbst zu testen …

Grüsse

Ja, das wirkt sich auf System.currentTimeMillis() aus. Ich kann mir nicht vorstellen, dass du das ohne immensen Aufwand verhindern kannst.
Eine Möglichkeit einen Zeitsprung festzustellen wäre, in einem separaten Thread sekündlich die Zeit abzurufen und dann mit dem erwarteten Wert zu vergleichen. So bekommst du wenigstens das Offset, um welches die Uhrzeit verstellt wurde, heraus.

Also das Thread.sleep(5000) ist auch nach dem Zeitumstellen trotzdem nur eine Dauer von 5 sec (weiß nicht wie das da intern gesteuert wird) aber System.currentTimeMillis() liefert die aktuelle Systemzeit. Wird diese während des Betriebes geändert, so wird bei einer neuen anfrage die neu eingestellte Zeit zurück geliefert.
Wie man es blockieren kann keine Ahnung, jedoch ist der Ansatz von @cmrudolph ein, denke ich, gut machbarer Ansatz.
Des weiteren benötigt man auf Win7, meine ich, auch Adminrecht um die Zeit zu verstellen.

Das Unschöne dabei ist eben, dass z. B. bei Thread.sleep(5000) der echte Zeitunterschied um ca. 10 Millisekunden vom erwarteten Zeitunerschied abweicht (der Thread hat dann 5010 Millisekunden geschlafen). Deswegen wollte ich auf System.currentTimeMillis() zurückgreifen, um quasi den „echten“ Zeitunterschied zu bekommen. Bloss macht das keinen Sinn, wenn die Zahl manipulierbar ist.

Mit diesen 10 Millisekunden Abweichung kann ich zwar leben, aber 0 wären nun mal am besten :wink: Schlussendlich gehts um Zeitspannen von 30 bis 60 Minuten, die ich abmessen muss. Wie hoch die Abweichung da ist, teste ich gerade …

Das wirst du aber je nach verwendetem OS sowieso nicht erreichen, da die Auflösung meist eh nicht millisekundengenau ist.
Unter Windows XP beispielsweise lag die Auflösung bei etwa 15ms, siehe hier: http://stackoverflow.com/questions/7859019/system-currenttimemillis-is-not-accurate-on-windows-xp

Du musst ein Zeitintervall von 30-60 Minuten auf die Millisekunde genau abmessen? Das hört sich irgendwie ungewöhnlich an. Und der seltene Fall, dass sich zwischendurch mal die Uhrzeit ändert (meistens wahrscheinlich, weil mal wieder Zeitumstellung ist) ist bedeutend, weil das Programm dauerhaft läuft?
Poste doch mal ein paar weitere Informationen zu deinem Programm.

wie stellst du das fest wenn nicht auch schon mit System.currentTimeMillis()?

und ich glaube es war/ ist in diesem Fall so, dass das sleep() schon korrekt arbeitet, nur System.currentTimeMillis() ungenau ist, nur ab und zu dann gleich 10-15ms weiterspringt,

nanoTime() gibts auch noch, genauer, aber ohne festen Bezug, da muss man von einem Startwert aus rechnen


nebenbei, und was ich eigentlich posten wollte, oben noch bisschen zum Thema gefunden:
Präfix ‚Erste Schritte‘ ist System.currentTimeMillis() nun kaum mehr, schon gar nicht mit Thread.sleep()/ Fragen zur Manipulation im Betriebsssystem,
ohne Präfix hier in ‚Java-Grundlagen‘-Area ausreichend platziert, wenn überhaupt hier passend, aber muss ja nicht nur ‚Erste Schritte‘ sein

bitte etwas bewußter mit den Präfixen umgehen, dürfte mit einfachen int-Berechnungen und for-Schleifen und Klassen + Objekte ausreichend besetzt sein,
edit: gibt freilich noch mehr Präxife speziell zu einigen dieser genannten Themen…

Naja, das Problem hat man nicht immer, aber bei allen klassischen Betriebssystemen. Bei einem RTOS könnte es klappen, bzw einem Umfeld von reinen Echtzeitsystemen, die immer nur eine genaue Dauer haben.

auf System.currentTimeMillis() wirkt sich das aber nicht aus, wäre ja noch schöner :wink:
nur interessant falls man das zu einer Uhrzeit in Textform umwandelt, zusammen mit Zeitzonen-Angabe auch dann noch eindeutig lösbar,
zumindest formel, ob es jeder lesen kann ist andere Frage…

Bist du dir da sicher? Ich habe vor dem Posten extra ein kleines Beispielprogramm geschrieben und während der Wartezeit die Uhrzeit um 10 Minuten zurückgedreht:

    public static void main(String... args) {
        long start = System.currentTimeMillis();
        sleep(20000);
        System.out.println(System.currentTimeMillis() - start);
    }

    private static void sleep(final long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ignored) {
        }
    }
}```

Das Resultat war ein Wert von -581.469 (bei 10 Minuten Uhr zurück). Also ein Versatz von 9 Minuten und 41 Sekunden.

ja, wenn man die Uhrzeit umstellt ist das mies,
ich meine dass die Sommerzeit-Umstellung keine Auswirkungen hat, wie auch Zeitzonenumstellungen an sich,

der Millizähler zählt seit 1.1.1970, das geht stoisch Schritt für Schritt voran, egal wie lahm Erde, Sonne und Mond sind
und Menschen Schaltjahre/ Sekunden einbauen,
egal ob man deutsche Tageszeit oder amerikanische Nachtzeit für den Augenblick nimmt und egal auch der Sommerzeit-Konvention gegenüber

eine physische Uhr mit Zeigern und auch ein interpretierender String „02:33“ muss merkwürdig springen,
die abstrakte Zeitzählung des Universums und des Atoms steht über so etwas :wink:

[QUOTE=SlaterB]ja, wenn man die Uhrzeit umstellt ist das mies,
…[/QUOTE]
Ja aber genau das wollte der TO doch wissen (habe in seinem Post die zwei stellen mal markiert.

[QUOTE=phpascal;85448]Hallo,

ich soll für die Schule ein kleines Java-Programm schreiben, das unter anderem auch mit System.currentTimeMillis() die aktuelle Zeit abholt und damit Messungen anstellt. Im Auftrag ist auch ganz klar festgehalten, dass das Programm so zu schreiben ist, dass der Benutzer die Zeit nicht irgendwie manipulieren kann.

Meine Frage wäre nun, ob diese Voraussetzung bei System.currentTimeMillis() gegeben ist, sprich, wenn ich am Computer, während das Programm läuft, in den Einstellungen die Uhrzeit ändere, sich dies auch auf System.currentTimeMillies() auswirkt? Falls ja, gibt es eine Möglichkeit, wie ich das verhindern kann?

Ich habe im Moment leider keinen Computer mit genug Rechten zur Hand, um das selbst zu testen …

Grüsse[/QUOTE]
Und da ist wie gesagt System.currentTimeMillies() nicht sicher oder wie auch @cmrudolph schon geschrieben bzw ausgetestet hat. Ich habe keine Ahnung warum Thread.sleep() trotzdem nur die angegebenen Sekunden unterbricht (wahrscheinlich wird das vom OS mit gesteuert und das schaut nur auf Takte oder so)
Aber wie ich schon sagte, bin ich der Meinung, dass diese Manipulation unter Win7 Adminrechte braucht. Wenn also nun die Schüler an den Rechnern an denen es ausgeführt wird keine Adminrechte hat, sollte es zur Zeitmessung passen.

aber zumindest der durchaus häufig auftretende, nicht vermeibare Fall der automatischen Zeitumstellung ist kein Problem,
speziell deswegen muss man nicht aufpassen zu System.currentTimeMillies(),

darauf bezog ich mich, trotz Zitat noch etwas deutlicher hätte gewiss nicht geschadet,
der allgemeine Fall schien mir aber so klar, sieht ja jeder dass das Java-Programm sich nach der Systemzeit richtet, wonach auch sonst,

Das ist meiner Meinung nach auch der einzige Fall, bei dem es zu einem echten Problem hätte werden können. Mutwillige Änderung der Zeit ist wohl eher ein theoretisches Problem.

Zeit per NTP beziehen ^^

Naja, laut der Fragestellung geht es aber genau um dein „wohl eher ein theoretisches Problem“ und nicht um irgendwelche anderen Probleme :wink:

Wie viel Latenz hat man den dabei? Da der TO ja schon 10ms Ungenauigkeit nicht so toll fand

Du kannst doch einen einen Timer so einstellen, dass er fix alle X millisekunden einen Task aufruft. Das sollte am genauesten funktionieren. Das geht mit scheduleAtFixedRate

[QUOTE=TheUnregistered]
Wie viel Latenz hat man den dabei? Da der TO ja schon 10ms Ungenauigkeit nicht so toll fand[/QUOTE]

Ausreichend um die Systemzeit sekundengenau oder genauer zu bestimmen. Der Rest bitte im RFC zu NTP nachlesen.

Dem TO haben die 10ms wohl eher geschreckt, da er von 5 Sekunden auf 30/60 Minuten hochrechnete, wo natürlich arge Differenzen auftreten.

Nichtsdestotrotz wüsste ich gern etwas mehr über die konkrete Problemstellung - weshalb soll das Verstellen der Uhrzeit ein relevantes Problem sein?

Also wenn du mit Hausmitteln arbeiten willst, hat SlaterB denke ich die Möglichkeit schon genannt - “System.nanoTime() * 1000000”. Soweit ich weiss wird dieser Timer nicht durch eine Zeitverstellung beeinflusst. Gut, dein Programm läuft evtl. nur noch ca. 292 Jahre, aber das reicht doch auch oder nicht?