# Klasse für GC freigeben



## Sehales (5. Dez 2012)

Hi,
mein Programm kann wärend des Laufens um neue Funktionen erweitert werden(ist für einen Gameserver der soll halt nicht offline gehen) neue "addons" werden einfach per URLClassLoader geladen und ich aktiviere sie dann über einen Aufruf der methode "onEnable()" und deaktiviere sie über "onDisable()", wenn ich nun die jar des addons nach dem deaktivieren löschen möchte meint windows dass ich das nicht kann weil die jar läuft, logisch die Klasse ist ja noch geladen.
Gibt es eine Möglichkeit in der Klasse eine "Selbstzerstörung" auszulösen ohne mein eigentliches Programm ins Jenseits zu befördern?
Wenn ich System.exit() aufrufe wird ja auch mein Programm geschlossen...
Ich habe etwas darüber gelesen dass man die Classloader in einer Liste speichern soll und darüber soll man dann die Klassen "unloaden" können, aber wie soll das gehen? Der Classloader bekommt dadurch ja trotzdem keine unload() Funktion...

MfG
Sehales


----------



## tröööt (5. Dez 2012)

URLClassLoader implementiert seit Java7 das neue AutoCloseable -interface und damit auch das Closeable -interface ... ergo : es gibt URLClassLoader.close() ...

zur funktionisweise : du musst ALLE referenzen auf bzw in den vom url-cl geladenen klassen KOMPLETT auf NULL setzen ... und dann auf die referenz des URLClassLoader einfach .close() callen .. am ende noch dessen referenz NULL .. und DANN kannst du das JAR einfach löschen und ersetzen ...

in wie fern es dann mit dem re-load von lediglich editierten klassen weitergeht müsste man sehen ob irgendwo caches vorhanden sind und diese ggf leeren ...


----------



## Sehales (5. Dez 2012)

ok danke dazu erstmal, einziges Problem, ich darf kein Java 7 verwenden....Java 7 ist zum Beispiel auf debian nicht als stable eingetragen und daher laufen viele debian server mit Java 6 und auch viele Home PC's haben noch Java 6.


----------



## TKausL (5. Dez 2012)

Sehales hat gesagt.:


> ok danke dazu erstmal, einziges Problem, ich darf kein Java 7 verwenden....Java 7 ist zum Beispiel auf debian nicht als stable eingetragen und daher laufen viele debian server mit Java 6 und auch viele Home PC's haben noch Java 6.



Wo ist genau dein Problem damit, dass die classes geladen bleiben?

Entweder es ist eine Endanwender-Anwendung wo es relativ egal ist ob die Klassen geladen bleiben oder nicht, oder aber du planst Plugins im laufenden Betrieb durch neuere Versionen zu ersetzen, wobei dir als Entwickler und Serverbesitzer freisteht JRE 7 zu installieren.
Ich selbst nutze auf einem Debian jetzt seit über 6 Monaten JRE 7 problemlos.


----------



## Sehales (6. Dez 2012)

jre7 läuft auch gut aber es sind anscheinend viele Serverbesitzer der Meinung dass alles was nicht als stable gekennzeichnet ist nicht genutzt werden soll, warum auch immer.... es soll möglich sein im laufenden Betrieb die Plugins/Addons durch neue Versionen zu ersetzen. Was ich machen könnte aber als unsauber erachte wäre die geladenen Klassen umzuschreiben per ASM und bei dem nächsten neustart des servers dann die jars zu ersetzen, das wäre die Lösung wenn gar nichts mehr geht, aber lieber verzichte ich darauf und man muss sich halt zweimal überlegen ob man die neuen Features jetzt nimmt...


----------



## tröööt (6. Dez 2012)

//EDIT
@TO
sorry ... habe meinen post geschrieben während du deinen geschrieben hast
für genau deinen anwendungsfall steht unten die lösung ...


musste zwar etwas suchen .. habs aber dann doch gefunden ...

es wurde mal im Sun-Bugtracker bereits zu zeiten von ich glaube 1.2 oder 1.3 als "Bug" bemängelt das man doch bitte close() in URLClassLoader einbauen soll .. was ja mit java7 endlich getan wurde ...

ein findiger programmierer hat dann als antwort diesen "hack" gepostet ...
getestet habe ich ihn selber nur unter Java6 ... er sollte aber meiner meinung nach auch noch unter 1.5 und mit ein paar weiteren tricks vielleicht sogar unter 1.4.2 lauffähig sein


```
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.jar.*;
import sun.misc.*;
import java.lang.reflect.*;
public class CustomURLClassLoader extends URLClassLoader implements Closeable
{
    public CustomURLClassLoader(URL[] url)
    {
        super(url);
    }
    public void close()
    {
        try
        {
            Class clazz=java.net.URLClassLoader.class;
            Field ucp=clazz.getDeclaredField("ucp");
            ucp.setAccessible(true);
            Object sun_misc_URLClassPath=ucp.get(this);
            Field loaders=sun_misc_URLClassPath.getClass().getDeclaredField("loaders");
            loaders.setAccessible(true);
            Object java_util_Collection=loaders.get(sun_misc_URLClassPath);
            for(Object sun_misc_URLClassPath_JarLoader : ((Collection) java_util_Collection).toArray())
            {
                try
                {
                    Field loader=sun_misc_URLClassPath_JarLoader.getClass().getDeclaredField("jar");
                    loader.setAccessible(true);
                    Object java_util_jar_JarFile=loader.get(sun_misc_URLClassPath_JarLoader);
                    ((JarFile) java_util_jar_JarFile).close();
                }
                catch (Throwable t)
                {
                    // if we got this far, this is probably not a JAR loader so skip it
                }
            }
        }
        catch (Throwable t)
        {
            // probably not a SUN VM
        }
        return;
    }
}
```

zur erklärung falls es aus dem code nicht klar wird ...

normalerweise setzt man URLClassLoader in verbindung mit JAR-files ein ...
der code oben macht nun folgendes :
1) zugriff auf private variable "URLClassLoader.ucp" vom type "sun.misc.URLClassPath"
2) zugriff auf private variable "sun.misc.URLClassPath.loaders" vom type "ArrayList<sun.misc.URLClassPath.Loader>" (nested class)
3) iteration über die ArrayList
4) zugriff auf private variable "jar" vom type "JarFile" in "sun.misc.URLClassPath.JarLoader" (nested class extends sun.misc.URLClassPath.Loader (nested class))
5) closen des File-handles auf das JAR-file

sieht man sich dazu den source des aktuellen java7 an stellt man fest das dieser nach dem selben prinzip arbeitet ... lediglich das direkt closen des JarFile wurde in die klasse sun.misc.URLClassPath selbst verlegt ...

zu beachten ist folgendes : dieser code ist so nur unter einer Sun / Oracle VM garantiert da auf sun.misc.* zugegriffen wird ...

sollte z.B. IcedTea verwendet werden ist die arbeitsweise entsprechend den dortigen klassen anzupassen ...

warum du allerdings immer noch Java6 nutzt verstehe ich nicht ...
gut ... selbst mit Update9 hat Java7 immer noch einige (teils schwere) bugs ... jedoch wird ein upgrade empfohlen ... und Oracle Java7 ist mitlerweile auch für unix verfügbar und wird von Oracle selbst als "stable" gemarked ...
wenn der distributor Java7 noch nicht getestet hat oder sich auf z.B. OpenJDK oder IcedTea verlässt welche noch kein stable v7 release haben solltest du dir überlegen einfach die Oracle VM zu nutzen ...

naja wie dem auch sei : einen (zumindest unter Oracle VM) lauffähigen "hack" für URLClassLoader.close() hast du jetzt ...

hope it helps ...


@TKausL
ich schätze dein fachwissen sehr und bin manchmal sogar etwas erleichtert das du teilweise sogar ähnliche ansichten und auffassungen hast wie ich ... jedoch geht es in diesem fall eben genau darum das es ein problem ist wenn eine klasse geladen bleibt ... nämlich z.B. dann wenn man diese während der runtime komplett austauschen möchte ohne die ganze VM neu starten zu müssen ... was gerade bei hoch-modularen systemen durch aus wichtig sein kann ...

ich selbst sitze grade an der entwicklung eines kleinen modularen systems (natürlich basis Java7) was z.b. solche applikaitonen ermöglicht ...
natürlich bin ich damit noch nicht fertig und ich habe noch leichte probleme es zu "verallgemeinern" (es ist noch stark auf das eigentliche ziel-projekt zugeschnitten) ... muss dabei jedoch auch selbst rückschläge in kauf nehmen .. wie z.B. das es java NICHT zulässt einem eigenen ClassLoader einen eigenen SecurityManager mitzugeben sondern diesen nur global für die gesamte VM zu setzen ... (ist zur zeit das hauptproblem : sicherheits-management)

vielleicht ist es im falle von TO eben nicht egal ob in einer end-user app eine klasse geladen bleibt ... er also die lösung nicht nur für sich selbst braucht ...

wobei ich hier denke das du mit mir zusammen in die richtung gehen würdest das man ein upgrade auf Java7 auch im produktiven umfeld so langsam mal ins auge fassen sollte


----------



## Spacerat (6. Dez 2012)

Okay, warum man noch ältere Javaversionen nutzt ist eine Sache...
Aber wieso man "Hacks" anbietet, die dann nur auf bestimmten JVMs laufen eine andere.

Es ist in so ziemlich jeder bekannten JVM möglich Archive komplett in ein Verzeichnis zu entpacken und dieses Verzeichnis zur Laufzeit mittels URLClassloader dem Classpath hinzuzufügen. Der URLClassloader lädt seine Klassen dann nicht aus dem Archiv, sondern aus dem Verzeichnis. Ich hatte so etwas schon mal selbst fabriziert, glaub' aber kaum, dass ich den Code noch finde, weils zu lange her ist (zu der Zeit waren gerade mal Java1.3 oder Java1.4 aktuell).
Eclipse verwendet anscheinend ein ähnlich funktionierenden Classloader wie den von mir beschriebenen, nur dass dort halt keine Archive entpackt werden müssen, sondern lediglich Projektpfade an den Klassenpfad gehangen werden.


----------



## tröööt (6. Dez 2012)

scheint als ob du den sinn des ganzen nicht ganz erfasst hast ...

auch wenn (wie mir schon vor ein paar jahren gesagt wurde) es eigentlich hauptbestandteil eines jeden application-servers ist module zur runtime vollständig wieder freigeben zu können ... zu hat doch die "normale" möglichkeit für end-user erst mit java7 einzug in die API gehalten ...

das dieser "hack" (das wort stammt übrigens nicht von mir sondern vom autor dieses codes) nur auf einer Sun/Oracle-VM läuft ist schlicht damit erklärt das nun mal das package sun.* NICHT bestandteil der API ist sondern eigentum von Sun / Oracle und damit zu dessen propiertären kern gehört ...

und wie ich sagte : guckt man sich den source der aktuellen version 7 an so stellt man fest das die iteration über die loader-liste lediglich in die klasse URLClassPath selbst implementiert wurde ... wer weis wie diese intern arbeit ... dürfte aber auch wieder nur die close()-calls weiter an die gelandenen file-handles leiten ...

ich sagte ja : wenn man eine andere VM nutzt muss man den code lediglich auf die entsprechenden klassen anpassen ... womit der code selbst bis auf dieses kleine manko eigentlich schon auf allen gängigen VMs laufen sollte ...

es gibt nun mal einsatzgebiete , und davon ne ganze menge , wo es eben sinn macht die geladenen klassen wieder völlig zu entladen und das archiv wieder freizugeben ... ein temporäres entpacken ins file-system halte ich für keine praktikable lösung ... schon alleine da es unter windows beim namen "aux.class" krachen dürfte da ein files mit diesem namen nicht auf einem NTFS-drive unter windows angelegt werden kann (gibt von diesen "verbotenen" dateinamen noch ne ganze liste) ...

mal von abgesehen das es auch passieren kann (wie ich an anderer stelle erwähnte) wenn man sich drauf verlässt das es gewisse resourcen gibt die dann nicht mehr geladen werden können ...
ein JAR vor zugriff zu locken und erst nach entladen wieder freizugeben macht durch aus sinn ...


----------



## Spacerat (6. Dez 2012)

tröööt hat gesagt.:


> scheint als ob du den sinn des ganzen nicht ganz erfasst hast ...


Doch, ich erfasse... Der Sinn des Ganzen liegt darin Klassen dynamisch zu laden, zu entladen und beim Entladen deren Ressourcen wieder freizugeben. Das Thema gab es schon weit vor der 1.7 (hast du auch schon beiläufig angedeutet) und Lösungen gab es da auch diverse, mal bessere, mal schlechtere.
Was ich allerdings nicht erfasse, warum man das Ganze mit 'nem "Hack" implementieren muss, der nur auf einer VM lauffähig wäre, wo es doch viel sauberer mit regulären API-Mitteln realisierbar ist. Man kann mit der API ZIPs und JARs teilweise oder ganz in den Speicher oder der Platte entpacken und man kann sich obendrein eigene (URL)ClassLoader schreiben. An diese verbotenen Namen habe ich dazumal zwar nicht gedacht, aber das könnte man immer noch per File-URL-Mapping lösen (so würde ich das zumindest aufgrund deines Tips nun machen). Für den Classloader ist ja letztendlich nur der Bytecode interessant, der am Ende eh' per ByteArray übergeben wird.


----------



## Tomate_Salat (6. Dez 2012)

Ich würde ja einfach OSGi dafür nehmen...


----------



## FArt (6. Dez 2012)

Das schließen des Classloaders ist sinnvoll, weshalb man auch ab Java 7 dem Wunsch nachgekommen ist.

Davon abgesehen: ein Classloader wird (auch in JRE6) vom GC aufgeräumt, wenn auf keine seiner geladenen Klassen, deren Instanzen und auf den CL selber Referenzen existieren. Durch etwas unsauberes Arbeiten passiert das aber häufiger, dass (nur eine unbemerkte Referenz) die GC für diesen gesamten Bereich blockiert.

In der Regel muss man sich nämlich über GC keine Gedanken machen, außer evtl. über den zu konfigurierenden Algorithmus.... es funktioniert so wie man es braucht im Hintergrund.


----------



## trööt (6. Dez 2012)

@Spacerat
gut ... dann gib doch mal ein "VM-unabhängies" beispiel was man nicht unbedingt "ClassLoader-hack" bezeichnen würde (noch mal : der ausdruck kommt nicht von mir) und das gewünschte leistet ...
wie ich ja sagte : eine solche funktionalität ist ein wichtiger grundbaustein jedes app-servers ... aber auf möglich EE-techniken kann man hier nicht eingehen da es ja für die SE-api laufen soll ...

natürlich ist es ... ja wie soll ich es sagen ... zumindest VM-unabhängig mit ZIP/JAR-lib und nem komplett selbst implementierten ClassLoader zu arbeiten der eben NICHT daran gebunden ist das propiertäre (schreibt man das eigentlich so ?) klasse aus z.b. sun.* genutzt werden ...
das am ende defineClass mit nem byte-array gecallt wird weis ich ... aber nicht wie man eine so geladene klasse nun wirklich wieder komplett entladen kann .. also quais aus dem "cache" bekommt ..

auch interessant ist das angesprochene "in den RAM entpacken" ...
ich weis das es kein "RAM-File" gibt ... (wobei ich mir sowas gerne wünschen würde und sicher irgendjemand File oder RandAccessFile soweit bearbeitet hat das es 100% im RAM läuft ... wenn auch meinet wegen mit ner native-lib) ... aber wenn du mit "zip in den ram entpacken" darauf hinaus willst das du dir quasi das zip in byte-arrays in den ram legst und dann irgendwie dem classloader zuführst wäre man ja bei großen apps wieder an cli-parameter gebunden um der VM mehr RAM zu geben ... würde zumindest mit "ins file-system entpacken" nicht passieren ... aber davon bin ich wie gesagt zumindest persönlich kein wirklicher freund ...

würde also gerne mal ein beispiel sehen wie du damit "resourcen-effizient" umgehen würdest ...


@Tomate
hat man mir zu meinem modularen system auch mal gesagt ... da ich mich deutlich ausgesprochen habe das ich eben das nicht will habe ich mit hilfe dieses und anderer foren mitlerweile eine sehr gute lib zusammen bekommen ... ich muss diese nur mal endlich vom haupt-projekt lösen und "verallgemeinern" ...

@Fart
naja ... URLClassLoader.close() macht ja nichts weiter als halt über ihn geladene Jar-files wieder fürs system freizugeben und jegliche calls wie getResource() oder defineClass() mit exceptions blockiert ... da die resource ja nicht mehr zur verfügung steht

das problem ist einfach das selbst wenn man auf eine via URL-CL geladene klasse und den CL selbst ALLE referenzen entfernt der GC zwar das alles wegräumen KANN (ist ja nicht garantiert) ... aber den file-lock auf das JAR-file selbst eben NICHT auslöst ... zumindest nicht bevor es in Java7 AutoCloseable gab ... ergo : auch ein ganz simples beispiel würde dazu führen das trotzdem vom OS kommt : JAR locked ...

und genau hier greift halt URL-CL.close() ... mehr ist es eigentlich nicht

und über GC muss man sich schon gedanken machen ... zumindest in hoch-modularen systemen ... weil man sicherstellen muss das der GC den müll bereits aufgeräumt hat bevor man die resourcen entläd ...
ist alles etwas tricky als wenn man nur so normal alles zusammen in den CP wirft ...


----------



## Tomate_Salat (6. Dez 2012)

> hat man mir zu meinem modularen system auch mal gesagt ... da ich mich deutlich ausgesprochen habe das ich eben das nicht will habe ich mit hilfe dieses und anderer foren mitlerweile eine sehr gute lib zusammen bekommen ... ich muss diese nur mal endlich vom haupt-projekt lösen und "verallgemeinern" ...



Was spricht den gegen OSGi? Du hast die Probleme mit dem laden+freigeben nicht und dazu noch einige Extras (z.B. Services)


----------



## KSG9|sebastian (6. Dez 2012)

Dynamisches laden und entladen selbst programmieren halte ich für ziemlich gewagt.

Es gibt massig Projekte die daran verzweifeln - selbst mit OSGI/Eclipse funktioniert es nur bedingt, einfach ein Paket auszutauschen.
Wenn man nun unbedingt sowas möchte würde ich doch OSGI oder JRebel oder ähnliches empfehlen.


----------



## FArt (6. Dez 2012)

Tomate_Salat hat gesagt.:


> Was spricht den gegen OSGi? Du hast die Probleme mit dem laden+freigeben nicht und dazu noch einige Extras (z.B. Services)



Ist trotzdem kein Allheilmittel... man kann sich halt mit anderen Mitteln genau so, nur ein wenig anders, ins Knie schießen... aber eine Möglichkeit ist es allemal.


----------



## KSG9|sebastian (6. Dez 2012)

FArt hat gesagt.:


> Ist trotzdem kein Allheilmittel... man kann sich halt mit anderen Mitteln genau so, nur ein wenig anders, ins Knie schießen... aber eine Möglichkeit ist es allemal.



Aber besser man bindet sich ein Framework ans Bein was seit relativ langer Zeit produktiv im Einsatz ist und eine entsprechende Firma/Basis hinter sich hat als das man versucht das Rad neu zu erfinden und in jeden Fettnapf erneut springt..


----------



## Tomate_Salat (6. Dez 2012)

FArt hat gesagt.:


> Ist trotzdem kein Allheilmittel... man kann sich halt mit anderen Mitteln genau so, nur ein wenig anders, ins Knie schießen... aber eine Möglichkeit ist es allemal.



Hab ich auch nirgends behauptet. Aber OSGi bietet dir Vorteile, die eine eigenentwicklung nicht hat:
- Große Community + weite Verbreitung
- Fachliteratur
- neue Mitarbeiter kennen das System möglicherweise schon
- bringt z.B. noch Services mit 
- es existiert bereits
- Fehler können wegen der Community schneller gefunden werden
- weniger Wartungsaufwand


----------



## trääät (6. Dez 2012)

OSGi selbst hilft einem überhaupt nicht .. denn OSGi spezifiziert lediglich die API ...

wenn überhaupt dann kommt es auf die einzelnen implementierungen an ... und bevor ich mich da durchwühle ... und dann eventuell noch geld zahlen muss da nur eine kostenpflichtige implementierung das leistet was ich will ... ist es sehr wohl einfacher sein eigenes kleins modul-system zu schreiben ...


ich hasse es ... immer kommt diese totschlag-kürzel OSGI hier ... OSGi da ... aber mal wirklich auf die einzelnen implementierungen ... deren unterschiede und vor/nachteile geht niemand ein ... da wird man in der luft hängen gelassen ... und genau DAS ist einer der gründe warum ich mich persönlich gegen osgi stelle ... weil am ende muss man es doch selbst implementieren


----------



## Tomate_Salat (6. Dez 2012)

> wenn überhaupt dann kommt es auf die einzelnen implementierungen an ... und bevor ich mich da durchwühle ... und dann eventuell noch geld zahlen muss da nur eine kostenpflichtige implementierung das leistet was ich will ... ist es sehr wohl einfacher sein eigenes kleins modul-system zu schreiben ...


Weil Equinox und Felix so teuer sind oO



> weil am ende muss man es doch selbst implementieren


Hatte ich noch nie die notwendigkeit für :autsch:



> deren unterschiede und vor/nachteile geht niemand ein


bennene diese doch mal ;-)


----------



## KSG9|sebastian (6. Dez 2012)

trääät hat gesagt.:


> OSGi selbst hilft einem überhaupt nicht .. denn OSGi spezifiziert lediglich die API ...
> 
> wenn überhaupt dann kommt es auf die einzelnen implementierungen an ... und bevor ich mich da durchwühle ... und dann eventuell noch geld zahlen muss da nur eine kostenpflichtige implementierung das leistet was ich will ... ist es sehr wohl einfacher sein eigenes kleins modul-system zu schreiben ...
> 
> ...



NIH-Syndrom?

Natürlich kauf man sich mit ner Bibliothek wieder andere Dinge ein und man sollte abwägen was man einsetzt und was nicht.

Aber mit diesem "da programmier ich schnell mal was" kaufst du dir mindestens genauso viele Nachteile ein

Wenig Funktionalität als es Frameworks bieten
Ständig muss das Ding gewartet und erweitert werden
Nochmal in jeden Fettnapf hüpfen
Frickel-Lösung

Ich bin auch kein wirklicher Freund von OSGi, aber es gibt definitiv Einsatzgebiete dafür. Man könnte ja auch sagen "Warum das bescheuerte JEE einsetzen?"
Da kann ich mir doch genauso Servlets bauen die JEE nachahmen. Ein bissl DI, ein bisschen Sessionmanagement, ein wenig Usermanagement, ein bisschen hiervon, ein bisschen davon...und dann vergehen 2-4 Jahre und man stellt fest, das man ein unwartbares Monstrum entwickelt hat mit dem täglich 15 Entwickler beschäftigt sind, die Codebase ist 10x größer als die von JEE, kann aber 10x weniger, alle Entwickler sind unzufrieden weil die Architektur nicht auf eine "großes Framework" ausgelegt ist, überall an allen Ecken und Enden kracht es, neue Mitarbeiter brauchen ein halbes Jahr um überhaupt in den Gründzügen zu verstehen was das Ding macht, man setzt Tomcat 4 ein, weil das coole Framework auf keiner anderen Umgebung läuft, man hat eigene Connectionpools (ich könnte noch seitenlang weitermachen, aus eigener Erfahrung)....


----------



## Spacerat (6. Dez 2012)

trööt hat gesagt.:


> würde also gerne mal ein beispiel sehen wie du damit "resourcen-effizient" umgehen würdest ...


Was dazumal noch mit nem' heaphungrigen ByteArray ging, geht heutzutage natürlich mit 'nem (Direct)ByteBuffer...
Das ist natürlich noch Ausbaufähig (RandomAccess, ThreadSafe, usw.), aber es liegt mir fern, erfahrenen Entwicklern alles vorkauen zu wollen. Macht das Beste draus .

```
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;

public final class RamFile extends InputStream {
	private ByteBuffer buffer;
	private URL location;

	public RamFile(String filename) throws IOException {
		this(new File(filename));
	}

	public RamFile(File file) throws IOException {
		this(file.toURI());
	}

	public RamFile(URI uri) throws IOException {
		this(uri.toURL());
	}

	public RamFile(URL url, String file) throws IOException {
		this(new URL(url, file));
	}

	public RamFile(URL url) throws IOException {
		if (url == null) {
			throw new NullPointerException();
		}
		location = url;
		URLConnection uc = url.openConnection();
		int l = uc.getContentLength();
		InputStream in = uc.getInputStream();
		buffer = ByteBuffer.allocateDirect(l);
		for(;buffer.position() < buffer.capacity();) {
			buffer.put((byte) in.read());
		}
	}

	@Override
	public int read(byte[] b) throws IOException {
		if(buffer == null) {
			throw new IOException("file closed");
		}
		buffer.get(b);
		return buffer.position();
	}

	@Override
	public int read(byte[] b, int off, int len) throws IOException {
		if(buffer == null) {
			throw new IOException("file closed");
		}
		buffer.get(b, off, len);
		return buffer.position();
	}

	@Override
	public int read() throws IOException {
		if(buffer == null) {
			throw new IOException("file closed");
		}
		return buffer.get() & 0xFF;
	}

	@Override
	public void close() throws IOException {
		super.close();
		buffer = null;
		location = null;
	}

	public URL getLocation() {
		return location;
	}
}
```
...bin mir sicher, dass man auch daraus ein JarInputStream hinbekommt.
[EDIT][OT]Das Ganze geht, wie man sieht auch ohne OSGi. Ich selbst halte von Fremd-Frameworks nur sehr wenig. Liegt daran, dass ich etwas schaffen will, wozu es eigentlich nur 'ne JVM braucht und weder sich selbst noch Enduser von der Installation bzw. Distribution solcher FWs abhängig macht. Gerade bei meinem "Steckenpferd", der Datentyperkennung, sind diese FWs erstens nervig und grösstenteils sowas von über... bestes Beispiel ImageIO - schön, ein Modulares FW (für Bilder... toll :autsch, aber hat schon mal jemand dran gedacht, das nicht jede VM über AWT geschweige denn Java2D verfügt? Schon ist man wider dabei, sich ein FW für seine VM zu suchen, welches prinzipiell die selben Datentypen liest. Ohne mich, sag' ich mal... und ich bekomme das hin! Ist zwar schwierig, aber es wird, auch wenn's länger dauert.[/OT][/EDIT]


----------



## Sehales (6. Dez 2012)

ääääh, also irgendwo gab es dann lauter "Bahnhof" für mich...aufjedenfall erstmal vielen vielen Dank für die ganze Arbeit und für nicht ganz einstimmig bewertete Lösungsvorschläge 
Ich denke mal das ich die Lösung in Form des "Hacks" nehmen werde und mir die gängisten der JVM's anschauen werde um die Lösung auf den meisten Systemen zur Verfügung stellen zu können. 

Auf der JVM von Oracle läuft mein System jetzt schonmal und damit bin ich schonmal zufrieden genug... Java7 bietet echt viele tolle Möglichkeiten aber viele Informatiker die ich kenne sind der Meinung(und auch deren Firmen in denen sie arbeiten) dass doch Java7 nicht zumutbar wäre, ich würde es liebend gern nutzen aber wenn es dann die Endnutzer an die es eigentlich geht nicht nutzen, wo ist da dann der Sinn?
Auch verstehe ich nicht warum es angeblich nicht so einfach wäre die Oracle JVM unter debian 6.0 zu installieren, es würde angeblich soooo viele Abhängigkeiten geben... ääähm ja...

Ich persönlich nutze Windows zum entwickeln und testen (ja, leider Windoof, aber Linux läuft warum auch immer nicht auf dem Laptop..., aber das ist ne andere Geschichte) und habe natürlich nichts gegen Java7 wenn ich dann aber als Rückmeldung bekomme, "Wir bekommen den Fehler unsupported major.minor version 51.0" und ich dann antworte man solle doch einfach Java7 nutzen, bekomme ich die Antwort das ja Java6 noch der Standart wäre und ja sogar viele Firmen noch für Java5 entwickeln.

Ich "programmiere" nur als Hobby oder vielleicht mal gegen nen minimales Endgeld aber grundätzlich habe ich weder eine Ausbildung noch ein Studium(wobei ich das für die Zukunft vor habe) und mache das jetzt seit ca. einem Jahr, ich denke dass ich einfach noch etwas warten werde und man halt ein Plugin nicht updaten kann wenn man keine der jvm's hat die ich halt unterstütze...gut ists.

Mal eine andere Frage, ist Java7 denn jetzt bugfrei/stabil/besser/schlechter was sind die Vorteile/was sind die Nachteile von Java7 gegenüber Java6 und warum wird Java5/Java6 meistens noch in Firmen verwendet statt Java7 wenn doch mit Java7 so viel mehr möglich ist und man es ja anscheinend doch recht einfach bekommt(hab mir grade mal angeguckt was anscheinend as Problem vieler ist das man Oracle's JVM für Java7 unter zum Beispiel Debian manuell installieren muss da es das in den offiziellen Paketen nichtmehr gibt weil anscheinend ständig die Lizenzbedingungen geändert werden Quelle: Java7-Debian)? Gibt es dafür Erklärungen?

Danke für die Antworten!

MfG
Sehales


----------



## trööt (7. Dez 2012)

nun ... warum viele kein major-upgrade durchführen sondern stattdessen nur updates einpflegen ... darüber habe ich so meine ganze eigenen gedanken ... aber auf grund meiner in vielerlei hinsicht doch scheinbar zu-radikalen denkweise für diesen staat enthalte ich mich mal weiterer äußerungen ...

Java7 STABLE zu nennen würden viele jetzt nicht unbedingt machen da es doch noch recht viele bugs enthält die schon zu zeit des early-access gemeldet und selbst mit Update9 immer noch nicht korrigiert wurden ...

vorteile sind ganz klar :

try-with-resources
AutoCloseable
NIO.2 FILE
AIO
JavaFX

um mal nur die "ganz großen" veränderungen zu nennen ...

nachteile dürfte es auch geben ... auch wenn mir jetzt persönlich noch keine bekannt sind ... (außer irgendjemand verschläft im JNLP einer WebStart-app in der version das "+" ... dann bewirkt "1.6" nämlich das ausführung mit ner 7er VM blockiert wird ... dafür muss es richtigerweise "1.6+" heißen ... warum auch immer wobei java ja eigentlich aufwärts-kompatibel ist im sinne von as 6er code mit ner 7er VM ausgeführt werden kann) ...


zur einstellung das du vom kunden Java7 verlangst : wenn der kunde sich nicht drauf einlässt wird er sich einen anderen entwickler suchen der Java6 code schreibt ... obwohl diese verhaltensweise meiner ansicht nach komplett falsch ist ...

auch ist es teilweise schuld von Sun / Oracle das diese die neuen major-versionen nicht zwingend/bindet durchsetzen sondern lediglich nach "hier habt ihr ..." vorgehen ... wobei es so viele andere möglichkeiten geben würde ... aber einiges davon ist konzeptionell bedingt ...


und die binary-license hängt mit der übernahme von Sun durch Oracle zusammen ... denn Oracle wollte von anfang an keine freie unkontrollierte distribution der binary-files ... so wie es Sun jahrelang gemacht hat ...
ich vermute hier steckt markt-politisch was dahinter ... vermutlich nach dem motto : hier guckt euch unsere download-zahlen an ... oder was weis ich ... auf jeden fall geht es dabei um viel geld was sich Oracle nicht so einfach durch die lappen gehen lässt wie Sun ... obwohl Java selbst unter freier lizenz steht und somit ohne konsequenzen von distributoren weiterhin auch im binary-format dem system beigelegt werden könnte ...

grundsätzlich gilt aber (um nun doch mal etwas anzureißen) : irgendwer wird mal ne ganz schlaue rechnung gemacht haben bei der rauskam das es "billiger" ist einfach Java6Update36 auf Update37 zu bringen anstatt gleich auf Java7Update9 umzusteigen ... wobei ich diese rechnung gerne mal erklärt hätte ...


----------



## Spacerat (7. Dez 2012)

trööt hat gesagt.:


> ... wobei ich diese rechnung gerne mal erklärt hätte ...


Kürzere Filesize (weil da steht ja gross UPDATE) bedeuten kürzere Downloadzeiten, sparen Strom und Traffic wodurch das Ganze kostengünstiger wird. :lol:
Das hinter diesen Updates aber grundsätzlich komplette Neuinstallationen hängen hat denen anscheinend noch keiner erklärt. Ist zwar alles rein hypothetisch, aber neben "Never touch a running Sytem" will mir beim besten Willen keine bessere Erklärung einfallen.
Okay, eine hätt' ich noch... Jene, die so denken, scheuen vor der Installation solcher "Hacks" (das der Ausdruck nicht von dir stammt, ist mir im übrigen klar) nicht zurück. Solche "Hacks" aber könnten in Future-Releases nicht mehr lauffähig sein, weil Oracle etwas an ihrem "Core" geändert hat. Ein Beispiel dazu wäre "<sun.image.SunWritableRaster>.notifyChanged()". Wer diese Methode in seinen Programmen trotz der Warnung, dass man diese Pakete meiden sollte, verwendet hat, geht mit Java7 gepflegt auf die Bretter (eigene Erfahrung ).


----------



## tröööt (7. Dez 2012)

auch wenn der text ironisch gemeint ist ... so sagt er dennoch irgendwie das aus was ich mir persönlich bei genau solchen leuten denke ...

und das ihr euch alle an diesem wort "Hack" aufgeilt ... ja ... ich hab auch kein bock mehr auf das thema ... zu mal es gelöst ist und wir eh OT sind ...


----------

