我有一個Java應用程序,除其他外,每小時發送到我們的Active Directory服務器,並拉下所有帳戶的列表,並將它們轉儲到數據庫中;這項工作是通過一個每小時產生一個新的線程完成的,數據庫接口是通過Hibernate完成的。該線程的run方法(基本上是這個線程做的唯一的事情)看起來像這樣:休眠內存堆錯誤
public void run() {
try {
Thread.sleep(3600000); //we run once an hour, so we sleep for an hour
Thread newHourlyRunThread = new Thread(new HourlyRunThread());
newHourlyRunThread.start();
LDAPNewUsersReport report = new LDAPNewUsersReport();
Calendar calendar = Calendar.getInstance();
calendar.set(0, 0, 0, 0, 0); //We tell the report to look for everything from 12AM Jan 1 0 AD, which should be sufficient to find all created AD objects.
report.runReport(calendar.getTime(), new Date());
HashSet<LDAPEntry> allEntries = report.getAllEntries();
Iterator it = allEntries.iterator();
while (it.hasNext()) {
ContactParser.parseContact((LDAPEntry) it.next());
}
}
從ContactParser相關的方法如下:
public static void parseContact(LDAPEntry entry) {
Contact chosenContact = null;
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List contacts = session.getNamedQuery("ContactByCanonicalName").setString(0, entry.getDN()).list();
Iterator it = contacts.iterator();
if (it.hasNext()) {
chosenContact = (Contact) it.next();
chosenContact = ContactParser.fillContactFields(chosenContact, entry);
} else {
chosenContact = ContactParser.fillContactFields(new Contact(), entry);
}
session.saveOrUpdate(chosenContact);
session.getTransaction().commit();
}
private static Contact fillContactFields(Contact chosenContact, LDAPEntry entry) {
chosenContact.setCanonicalName(entry.getDN());
chosenContact.setFirstName(ContactParser.getEntryField(entry, "givenName"));
chosenContact.setLastName(ContactParser.getEntryField(entry, "sn"));
chosenContact.setUserName(ContactParser.getEntryField(entry, "sAMAccountname"));
chosenContact.setEmployeeID(ContactParser.getEntryField(entry, "employeeID"));
chosenContact.setMiddleName(ContactParser.getEntryField(entry, "initials"));
chosenContact.setEmail(ContactParser.getEntryField(entry, "mail"));
if(chosenContact.getFirstSeen() == null){
chosenContact.setFirstSeen(new Date());
}
chosenContact.setLastSeen(new Date());
return chosenContact;
}
private static String getEntryField(LDAPEntry entry, String fieldName){
String returnString = "";
if(entry.getAttribute(fieldName) != null){
returnString = entry.getAttribute(fieldName).getStringValue();
}
return returnString;
}
這所有的作品非常漂亮,如果我們只運行一個單一的實例(所以,沒有新的線程是事後產生的),但如果我們不止一次運行這個線程(IE,我加快執行到~30秒,以便我可以看到問題),Hibernate報告缺乏堆空間。這看起來不像是一組特別強烈的數據(只有大約6K條目),但是當我們將代碼碰到分級錯誤以準備推進生產時,我看到了同樣的錯誤。在編寫高效的線程方面我缺乏經驗,而在Hibernate方面缺乏經驗,所以如果有人有一個想法,可能會耗盡我們的堆空間(這個應用程序中的另一個主要線程沒有同時運行,並且佔用了幾百千字節的內存),我非常感謝任何建議。
在此先感謝。
您是否嘗試過分析該應用程序?另外,請查看'-Xmx'和'-Xms'命令行參數。有一些有用的(和免費的)用於Java的內存分析軟件包。 – 2010-10-05 15:00:07
@Dave Jarvis:現在嘗試進行配置。至於增加堆大小:理想情況下,我想盡量避免這種情況,因爲這最終將在具有許多其他進程的服務器上運行,並且我想成爲一個好公民,而不是需要巨大的這是一個小小的應用程序的記憶堆。 – EricBoersma 2010-10-05 15:05:26