DatenquellenUpdater extends Thread - Problem mit PermGenSpace

brauner1990

Bekanntes Mitglied
Mahlzeit und Guten Tag Community,

ich habe mir eine Klasse geschrieben, welche als eigentständiger Thread fungieren soll. Hierbei tritt nun des öfteren ein PermGenSpace-Fehler auf. Könntet ihr mir dort mal weiterhelfen / erklären woran es liegen könnte?

Hier der Quellcode:

Java:
package esd.helfer;

import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import esd.entities.DatenquelleXml;
import esd.jpaController.JpaController;
import esd.jpaController.exceptions.PreexistingEntityException;

/**
 *
 */
public class DatenquellenUpdater extends Thread {

    private static DatenquellenUpdater instance;
    public static int durchlaeufe;

    private DatenquellenUpdater() {
        durchlaeufe = 0;
        this.setPriority(Thread.MAX_PRIORITY - 1);
        this.setName("eStatisticsDashboardDatenquellenUpdaterThread Prio:" + this.getPriority());
    }

    public static synchronized DatenquellenUpdater getInstance() {
        if (instance == null) {
            instance = new DatenquellenUpdater();
Calendar.getInstance().getTime() + " - " + " - NEW INSTANCE CREATED");
            String text = (Calendar.getInstance().getTime().toString() + " - DatenquellenUpdater started, now update process is running until undeploy Application eStatisticDashboard.");
            Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.INFO, text, null);
        }
        return instance;
    }

    @Override
    public synchronized void run() {
        JpaController jpc;
        List<DatenquelleXml> findObjectEntities;
        Date start, end;
        long diff;
        String text = "";
        while (true) {
            try {
                jpc = JpaController.getInstance();
                start = Calendar.getInstance().getTime();
                findObjectEntities = jpc.findObjectEntities(DatenquelleXml.class);
                for (DatenquelleRueiXml d : findObjectEntities) {
                    d.updateData();
Calendar.getInstance().getTime() + " - " + " - " + d.getId());
                }
                durchlaeufe++;
                end = Calendar.getInstance().getTime();
                if ((end.getTime() - start.getTime()) > 0
                        && (end.getTime() - start.getTime()) < (5 * 60 * 1000)) {
                    diff = (5*60*1000)-(end.getTime() - start.getTime());
                } else {
                    diff = 0;
                }
                if (durchlaeufe == 6) {
                    text = (Calendar.getInstance().getTime().toString() + " - DatenquellenUpdater pass all updates " + durchlaeufe + " time  eStatisticDashboard.");
                    Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.INFO, text, null);
                    durchlaeufe = 0;
                }
                if (diff > 0) {
                    DatenquellenUpdater.sleep(diff);
                }
                start = null;
                end = null;
                diff = 0;
                text = null;
                findObjectEntities = null;
                jpc = null;
            } catch (NullPointerException ex) {
                Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.ERROR, ex.getMessage(), ex);
            } catch (PreexistingEntityException ex) {
                Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.ERROR, ex.getMessage(), ex);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.ERROR, ex.getMessage(), ex);
            } catch (SQLException ex) {
                Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.ERROR, ex.getMessage(), ex);
            } catch (IllegalThreadStateException ex) {
                Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.ERROR, ex.getMessage(), ex);
            } catch (Exception ex) {
                Logger.getLogger(DatenquellenUpdater.class.getName()).log(Level.ERROR, ex.getMessage(), ex);
            }
        }
    }
}

[JAVA=344]

/**
* Diese Funktion schreibt die Datenquelle in die Datenbank
*/
public String datenQuellePersistieren() throws NullPointerException, PreexistingEntityException, ClassNotFoundException, SQLException, Exception {
BufferedReader br = null;
ArrayList<String> col = new ArrayList<String>();
if (this._ueberschreiben) {
try {
MsSql.getInstance().dropTable(this._tableName);
} catch (ClassNotFoundException ex) {
Logger.getLogger(DatenquelleRueiXml.class.getName()).log(Level.ERROR, null, ex);
} catch (SQLException ex) {
Logger.getLogger(DatenquelleRueiXml.class.getName()).log(Level.ERROR, null, ex);
}
this.createTableForThis();
}
/* Pro Pfad einmal auslesen */
Set<String> cnfs = this.getColumnNamesFromSQL();
ArrayList<String> alcnfs = new ArrayList<String>();
for (String s : cnfs) {
alcnfs.add(s);
}
try {
br = Hilfe.getBufferedReaderFromHttpsUrl(this.getId());
String line;

line = br.readLine(); // Line enthaelt nur den XML Versions Tag (<?xml version="1.0" encoding="UTF-8"?>)
line = br.readLine(); // Line enthaelt nur den Tag fuer den Anfang des Reports (<report>)
/*
* Hier wird nun die ID ermittelt damit der Tabellen Name herausgefunden wird
*/
line = br.readLine();

br.readLine(); // Line enthaelt nur den Namen des Reports (<name>****</name>)

String toAdd;
while ((line = br.readLine()) != null) {
if (line.equals("<row>")) {

while (!(line = br.readLine()).equals("</row>")) {
toAdd=line.substring(line.indexOf("<name>") + 6, line.indexOf("</name>"));
if(toAdd.equals("n/a")){
toAdd="0";
}
col.add(toAdd);
}
try {
int anzahlDerNullwerte=0;
for(String s:col){
if(s.equals("0")){
anzahlDerNullwerte++;
}
}
if(anzahlDerNullwerte<(col.size())){
MsSql.getInstance().insertInto(this._tableName, col, alcnfs);
}
} catch (SQLServerException e) {
Logger.getLogger(DatenquelleRueiXml.class.getName()).log(Level.ERROR, null, e);
}
col.clear();
}
}
} catch (Exception ex) {
if (ex instanceof SQLServerException) {
throw (SQLServerException) ex;
}
Logger.getLogger(DatenquelleRueiXml.class.getName()).log(Level.ERROR, null, ex);
} finally {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(DatenquelleRueiXml.class.getName()).log(Level.ERROR, null, ex);
}
}
return "";
}

public String updateData() throws PreexistingEntityException, Exception {
String datenQuellePersistieren = this.datenQuellePersistieren();
this._lastUpdate = Calendar.getInstance().getTime();
JpaController jpc = JpaController.getInstance();
jpc.edit(this);
return "";
}[/code]

[JAVA=124]
/**
* Dieser Befehl fuegt nur eine Zeile hinu
* @param tableName
* @param values
* @return
*/
public void insertInto(String tableName, ArrayList<String> values, ArrayList<String> columns) throws NullPointerException, SQLException, ClassNotFoundException {
StringBuilder sbInsert = new StringBuilder();
StringBuilder sbSelect = new StringBuilder();
StringBuilder sbUpdate = new StringBuilder();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
int spaltennnummer = 0;
int pkcid = 0;
String firstWert = "";
try {
pkcid = MsSqlBefehlsvorlagen.findPrimaryKeyColumnId(tableName);
} catch (NullPointerException npe) {
throw npe;
}

ResultSet rs = this.executeQuery("SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE '" + tableName + "' ORDER BY ORDINAL_POSITION;");
boolean t = true;
boolean firstRun = true;
LinkedList<String> lls = new LinkedList<String>();
while (t) {
rs.next();
try {
lls.add(rs.getString(1));
} catch (SQLServerException sse) {
break;
}
}


sbInsert.append("INSERT INTO [dbo].[").append(tableName).append("] VALUES( ");
sbUpdate.append("UPDATE [dbo].[").append(tableName).append("] SET ");
for (String a : values) {
String b = a;
if (lls.get(spaltennnummer).equals("float")) {
a = a.replace(".", "");
a = a.replace(",", ".");
b = Double.valueOf(a).toString();
} else if (lls.get(spaltennnummer).equals("datetime")) {
String[] split = a.split(":");
Calendar calendarInstance = Calendar.getInstance();
calendarInstance.setTime(new Date());
calendarInstance.set(Calendar.HOUR_OF_DAY, Integer.valueOf(split[0]));
calendarInstance.set(Calendar.MINUTE, Integer.valueOf(split[1]));
calendarInstance.set(Calendar.SECOND, 0);
calendarInstance.set(Calendar.MILLISECOND, 0);

a = this.formatDateToString(calendarInstance.getTime());
b = this.formatDateToString(calendarInstance.getTime());

firstWert = a;
} else if (lls.get(spaltennnummer).equals("varchar")) {
a = a.replace(".", "");
a = a.replace(",", ".");
b = a;
if (firstRun) {
firstWert = a;
firstRun = false;
}
}
sbInsert.append("'");
sbUpdate.append("[").append(columns.get(spaltennnummer)).append("] = '");
sbInsert.append(b).append("',");
sbUpdate.append(b).append("',");
spaltennnummer++;
}
sbInsert.delete(sbInsert.length() - 1, sbInsert.length());
sbInsert.append(")");
sbUpdate.delete(sbUpdate.length() - 1, sbUpdate.length());
sbUpdate.append(" WHERE [").append(columns.get(pkcid - 1)).append("] = '").append(firstWert).append("'");
sbSelect.append("SELECT [").append(columns.get(pkcid - 1)).append("] FROM [dbo].[").append(tableName).append("] ").append(" WHERE [").append(columns.get(pkcid - 1)).append("] = '").append(firstWert).append("'");
String sql = "IF NOT EXISTS (" + sbSelect.toString() + ") " + sbInsert.toString() + " ELSE " + sbUpdate.toString();
this.executeSQL(sql);
}
[/code]

Ich hoffe ihr könnt mir helfen... Danke schonmal
 

Noctarius

Top Contributor
1. Ieh ein Singelton und auch noch ein ganz schlechtes (Multithreading)
2. Wieso jedesmal den Logger neu holen? Logger.getLogger(DatenquellenUpdater.class.getName())
3. Denglische und deutsche Mehodennamen gemischt
4. Denglische und deutsche Klassennamen gemischt
5. MsSql.getInstance().dropTable(...) - Wieso kann das eine ClassNotFoundException werfen?
6. ...

Bitte sag mir nicht, dass das in irgendeiner kommerziellen Software zu finden ist, und wenn doch in welcher, die will ich nicht kaufen ;) Das wird irgendwann nicht mehr wartbar, wenn es das nicht schon ist.
 

brauner1990

Bekanntes Mitglied
1. Ieh ein Singelton und auch noch ein ganz schlechtes (Multithreading)
Bin für alle Ideen offen. [EDIT] Habe mich nun informiert und bin zu folgender Lösung gekommen.
Java:
public class DatenquellenUpdater extends Thread {

    private volatile static DatenquellenUpdater instance;
    public static int durchlaeufe;
    private static Logger logger;

    private DatenquellenUpdater() {
        DatenquellenUpdater.logger = Logger.getLogger(DatenquellenUpdater.class.getName());
        durchlaeufe = 0;
        this.setPriority(Thread.MAX_PRIORITY - 1);
        this.setName("eStatisticsDashboardDatenquellenUpdaterThread Prio:" + this.getPriority());
    }

    public static synchronized DatenquellenUpdater getInstance() {
        if (instance == null) {
            synchronized (DatenquellenUpdater.class) {
                if (instance == null) {
                    instance = new DatenquellenUpdater();
                }
                String text = (Calendar.getInstance().getTime().toString() + " - DatenquellenUpdater started, now update process is running until undeploy Application eStatisticDashboard.");
                logger.log(Level.INFO, text, null);
            }
        }
        return instance;
    }
[/Edit]
2. Wieso jedesmal den Logger neu holen? Logger.getLogger(DatenquellenUpdater.class.getName())
Ok ... am besten abspeichern?
3. Denglische und deutsche Mehodennamen gemischt
4. Denglische und deutsche Klassennamen gemischt
Beschwer dich nicht, du durftest nicht diskutieren, ich habe mich über eine Stunde mit dem Architekten damit auseinander gesetzt, damit ich wenigstens wusste ich habs versucht. Der will das so, und ich darf das UML nunmal so umsetzen.
5. MsSql.getInstance().dropTable(...) - Wieso kann das eine ClassNotFoundException werfen?
In MsSql holt er sich ja auch die Connection, welche leider per Hand erstellen muss.

Bitte sag mir nicht, dass das in irgendeiner kommerziellen Software zu finden ist, und wenn doch in welcher, die will ich nicht kaufen ;) Das wird irgendwann nicht mehr wartbar, wenn es das nicht schon ist.
Nope ... Firmenintern
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
1. Singletons am Besten vergessen, wegwerfen, verbannen, ... und Dependency Injection einsetzen
2. private static final Logger LOG = Logger.getLogger(DatenquellenUpdater.class); z.b.
3. Architekten erdrosseln, erschießen, erwürgen, erstechen und dann erst kreativ werden
4. Komischer SQL Treiber aber gut, wieso von Hand, schon mal was von ConnectionPool gehört?
5. Glück gehabt ;)
 

brauner1990

Bekanntes Mitglied
1. Singletons am Besten vergessen, wegwerfen, verbannen, ... und Dependency Injection einsetzen
noch nie was von gehört .... ich werde mich da mal informieren, wenn du aber gute Links kennst, bitte posten
[EDIT]
Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 7.3 Service-Factory <-- ist dies hier die richtige Richtung für die eigene Implementierung?
[/EDIT]
2. private static final Logger LOG = Logger.getLogger(DatenquellenUpdater.class); z.b.
Java:
    private static final Logger logger=Logger.getLogger(DatenquellenUpdater.class.getName());
eingebaut ...
3. Architekten erdrosseln, erschießen, erwürgen, erstechen und dann erst kreativ werden
Leider verboten...
4. Komischer SQL Treiber aber gut, wieso von Hand, schon mal was von ConnectionPool gehört?
SQL - Treiber von Windows ... Schonmal was von Class.forName gehört?
Java:
private void connect() throws ClassNotFoundException, SQLException {
        if (cn == null) {
            /*Original von Bill Gates*/
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            cn = DriverManager.getConnection(cnUrl);

            Logger.getLogger(MsSql.class).log(Level.INFO, "Database Connection established ", null);
        }
    }
Das es nicht an den Kunden kommt? Nunja, der Kunde, die sind froh wenn Sie das endlich dürfen was das Programm zur Verfügung stellt.
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
Zu 1: Schau dir am Besten Google Guice an. Spring ist zwar auch sehr nett aber doch etwas größer angelegt. Wer reines DI will kommt mit Guice super zu Rande.
Motivation - google-guice - Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 5 and above, brought to you by Google. - Google Project Hosting

Und nein, eine Service-Factory ist kein echtes DI. Es geht in die Richtung aber mehr auch nicht.

Hier mal ein Artikel zu DI: Dependency Injection ? Wikipedia

Zu 4: Ja klar aber so macht man generell keine Datenbankverbindungen außer man übt wie man damit umgeht. Generell nutzt man Connection Pools wenn man es richtig machen will. Und wenn man den Treiber selber laden muss, dann reicht es am Anfang vom Programm und nicht jedesmal vor dem Abruf einer Connection.
 

Neue Themen


Oben