summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/ScopedGlobalRef.h5
-rw-r--r--include/ScopedLocalRef.h54
-rw-r--r--luni/src/main/java/com/ibm/icu4jni/util/ICU.java26
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java7
-rw-r--r--luni/src/main/native/ICU.cpp119
5 files changed, 127 insertions, 84 deletions
diff --git a/include/ScopedGlobalRef.h b/include/ScopedGlobalRef.h
index 15a9055..1fbeabb 100644
--- a/include/ScopedGlobalRef.h
+++ b/include/ScopedGlobalRef.h
@@ -19,7 +19,8 @@
#include "JNIHelp.h"
-// A smart pointer that provides access to a JNI global reference
+// A smart pointer that creates a JNI global reference from a weak reference.
+// The global reference is deleted when the smart pointer goes out of scope.
class ScopedGlobalRef {
public:
ScopedGlobalRef(JNIEnv* env, jobject localRef)
@@ -39,7 +40,7 @@ public:
}
}
- jobject get () const {
+ jobject get() const {
return mGlobalRef;
}
diff --git a/include/ScopedLocalRef.h b/include/ScopedLocalRef.h
new file mode 100644
index 0000000..2cf4673
--- /dev/null
+++ b/include/ScopedLocalRef.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SCOPED_LOCAL_REF_H_included
+#define SCOPED_LOCAL_REF_H_included
+
+#include "JNIHelp.h"
+
+// A smart pointer that deletes a JNI local reference when it goes out of scope.
+class ScopedLocalRef {
+public:
+ ScopedLocalRef(JNIEnv* env, jobject localRef)
+ : mEnv(env), mLocalRef(localRef)
+ {
+ }
+
+ ~ScopedLocalRef() {
+ reset();
+ }
+
+ void reset() {
+ if (mLocalRef != NULL) {
+ mEnv->DeleteLocalRef(mLocalRef);
+ mLocalRef = NULL;
+ }
+ }
+
+ jobject get() const {
+ return mLocalRef;
+ }
+
+private:
+ JNIEnv* mEnv;
+ jobject mLocalRef;
+
+ // Disallow copy and assignment.
+ ScopedLocalRef(const ScopedLocalRef&);
+ void operator=(const ScopedLocalRef&);
+};
+
+#endif // SCOPED_LOCAL_REF_H_included
diff --git a/luni/src/main/java/com/ibm/icu4jni/util/ICU.java b/luni/src/main/java/com/ibm/icu4jni/util/ICU.java
index b684068..30e7001 100644
--- a/luni/src/main/java/com/ibm/icu4jni/util/ICU.java
+++ b/luni/src/main/java/com/ibm/icu4jni/util/ICU.java
@@ -16,6 +16,7 @@
package com.ibm.icu4jni.util;
+import java.util.HashMap;
import java.util.Locale;
import java.util.TimeZone;
import java.util.logging.Logger;
@@ -157,21 +158,24 @@ public final class ICU {
arrayToFill[3] = new String[availableTimezones.length];
arrayToFill[4] = new String[availableTimezones.length];
- /*
- * Fill in the zone names in native.
- */
+ // Don't be distracted by all the code either side of this line: this is the expensive bit!
getTimeZonesNative(arrayToFill, locale);
- /*
- * Finally we need to reorder the entries so we get the expected result.
- */
+ // Reorder the entries so we get the expected result.
+ // We also take the opportunity to de-duplicate the names (http://b/2672057).
+ HashMap<String, String> internTable = new HashMap<String, String>();
String[][] result = new String[availableTimezones.length][5];
- for (int i = 0; i < availableTimezones.length; i++) {
+ for (int i = 0; i < availableTimezones.length; ++i) {
result[i][0] = arrayToFill[0][i];
- result[i][1] = arrayToFill[1][i];
- result[i][2] = arrayToFill[2][i];
- result[i][3] = arrayToFill[3][i];
- result[i][4] = arrayToFill[4][i];
+ for (int j = 1; j <= 4; ++j) {
+ String original = arrayToFill[j][i];
+ String nonDuplicate = internTable.get(original);
+ if (nonDuplicate == null) {
+ internTable.put(original, original);
+ nonDuplicate = original;
+ }
+ result[i][j] = nonDuplicate;
+ }
}
Logger.global.info("Loaded time zone names for " + locale + " in "
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
index f919b39..2c4aaf7 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
@@ -187,12 +187,7 @@ public class Header implements Cloneable {
}
/**
- * Returns the value corresponding to the specified key.
- *
- * @param key
- * the key to look up.
- * @return Answers the value for the given key, or <code>null</code> if no
- * such key exists.
+ * Returns the value corresponding to the specified key, or null.
*/
public String get(String key) {
LinkedList<String> result = keyTable.get(key);
diff --git a/luni/src/main/native/ICU.cpp b/luni/src/main/native/ICU.cpp
index 1945b69..63f62dd 100644
--- a/luni/src/main/native/ICU.cpp
+++ b/luni/src/main/native/ICU.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "ICU"
#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "UniquePtr.h"
#include "cutils/log.h"
@@ -215,9 +216,8 @@ static jobjectArray toStringArray(JNIEnv* env, const char* const* strings) {
}
jobjectArray result = env->NewObjectArray(count, string_class, NULL);
for (size_t i = 0; i < count; ++i) {
- jstring s = env->NewStringUTF(strings[i]);
- env->SetObjectArrayElement(result, i, s);
- env->DeleteLocalRef(s);
+ ScopedLocalRef s(env, env->NewStringUTF(strings[i]));
+ env->SetObjectArrayElement(result, i, s.get());
}
return result;
}
@@ -235,9 +235,8 @@ static jobjectArray getAvailableLocales(JNIEnv* env, Counter* counter, Getter* g
size_t count = (*counter)();
jobjectArray result = env->NewObjectArray(count, string_class, NULL);
for (size_t i = 0; i < count; ++i) {
- jstring s = env->NewStringUTF((*getter)(i));
- env->SetObjectArrayElement(result, i, s);
- env->DeleteLocalRef(s);
+ ScopedLocalRef s(env, env->NewStringUTF((*getter)(i)));
+ env->SetObjectArrayElement(result, i, s.get());
}
return result;
}
@@ -279,37 +278,34 @@ static jstring formatDate(JNIEnv* env, const SimpleDateFormat& fmt, const UDate&
return env->NewString(str.getBuffer(), str.length());
}
-static void getTimeZonesNative(JNIEnv* env, jclass, jobjectArray outerArray, jstring locale) {
- // get all timezone objects
- jobjectArray zoneIdArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 0);
- int count = env->GetArrayLength(zoneIdArray);
- TimeZone* zones[count];
- for(int i = 0; i < count; i++) {
- jstring id = (jstring) env->GetObjectArrayElement(zoneIdArray, i);
- zones[i] = timeZoneFromId(env, id);
- env->DeleteLocalRef(id);
- }
-
- Locale loc = getLocale(env, locale);
-
+static void getTimeZonesNative(JNIEnv* env, jclass, jobjectArray outerArray, jstring localeName) {
+ Locale locale = getLocale(env, localeName);
+
+ // We could use TimeZone::getDisplayName, but that's way too slow.
+ // The cost of this method goes from 0.5s to 4.5s on a Nexus One.
+ // Much of the saving comes from caching SimpleDateFormat instances.
UErrorCode status = U_ZERO_ERROR;
- UnicodeString longPattern("zzzz","");
- SimpleDateFormat longFormat(longPattern, loc, status);
- UnicodeString shortPattern("z","");
- SimpleDateFormat shortFormat(shortPattern, loc, status);
+ UnicodeString longPattern("zzzz", "");
+ SimpleDateFormat longFormat(longPattern, locale, status);
+ UnicodeString shortPattern("z", "");
+ SimpleDateFormat shortFormat(shortPattern, locale, status);
- jobjectArray longStdTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 1);
- jobjectArray shortStdTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 2);
- jobjectArray longDlTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 3);
- jobjectArray shortDlTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 4);
+ jobjectArray longStdArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 1);
+ jobjectArray shortStdArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 2);
+ jobjectArray longDstArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 3);
+ jobjectArray shortDstArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 4);
// 15th January 2008
UDate date1 = 1203105600000.0;
// 15th July 2008
UDate date2 = 1218826800000.0;
- for (int i = 0; i < count; ++i) {
- TimeZone* tz = zones[i];
+ jobjectArray zoneIds = (jobjectArray) env->GetObjectArrayElement(outerArray, 0);
+ int zoneIdCount = env->GetArrayLength(zoneIds);
+ for (int i = 0; i < zoneIdCount; ++i) {
+ ScopedLocalRef id(env, env->GetObjectArrayElement(zoneIds, i));
+ UniquePtr<TimeZone> tz(timeZoneFromId(env, reinterpret_cast<jstring>(id.get())));
+
longFormat.setTimeZone(*tz);
shortFormat.setTimeZone(*tz);
@@ -328,24 +324,23 @@ static void getTimeZonesNative(JNIEnv* env, jclass, jobjectArray outerArray, jst
standardDate = date1;
daylightSavingDate = date2;
}
-
- jstring content = formatDate(env, shortFormat, daylightSavingDate);
- env->SetObjectArrayElement(shortDlTimeArray, i, content);
- env->DeleteLocalRef(content);
-
- content = formatDate(env, shortFormat, standardDate);
- env->SetObjectArrayElement(shortStdTimeArray, i, content);
- env->DeleteLocalRef(content);
-
- content = formatDate(env, longFormat, daylightSavingDate);
- env->SetObjectArrayElement(longDlTimeArray, i, content);
- env->DeleteLocalRef(content);
-
- content = formatDate(env, longFormat, standardDate);
- env->SetObjectArrayElement(longStdTimeArray, i, content);
- env->DeleteLocalRef(content);
-
- delete tz;
+
+ ScopedLocalRef shortStd(env, formatDate(env, shortFormat, standardDate));
+ env->SetObjectArrayElement(shortStdArray, i, shortStd.get());
+
+ ScopedLocalRef longStd(env, formatDate(env, longFormat, standardDate));
+ env->SetObjectArrayElement(longStdArray, i, longStd.get());
+
+ if (tz->useDaylightTime()) {
+ ScopedLocalRef shortDst(env, formatDate(env, shortFormat, daylightSavingDate));
+ env->SetObjectArrayElement(shortDstArray, i, shortDst.get());
+
+ ScopedLocalRef longDst(env, formatDate(env, longFormat, daylightSavingDate));
+ env->SetObjectArrayElement(longDstArray, i, longDst.get());
+ } else {
+ env->SetObjectArrayElement(shortDstArray, i, shortStd.get());
+ env->SetObjectArrayElement(longDstArray, i, longStd.get());
+ }
}
}
@@ -395,12 +390,10 @@ static jobjectArray getAmPmMarkers(JNIEnv* env, UResourceBundle* gregorian) {
}
jobjectArray amPmMarkers = env->NewObjectArray(2, string_class, NULL);
- jstring amU = env->NewString(am, lengthAm);
- env->SetObjectArrayElement(amPmMarkers, 0, amU);
- env->DeleteLocalRef(amU);
- jstring pmU = env->NewString(pm, lengthPm);
- env->SetObjectArrayElement(amPmMarkers, 1, pmU);
- env->DeleteLocalRef(pmU);
+ ScopedLocalRef amU(env, env->NewString(am, lengthAm));
+ env->SetObjectArrayElement(amPmMarkers, 0, amU.get());
+ ScopedLocalRef pmU(env, env->NewString(pm, lengthPm));
+ env->SetObjectArrayElement(amPmMarkers, 1, pmU.get());
return amPmMarkers;
}
@@ -427,9 +420,8 @@ static jobjectArray getEras(JNIEnv* env, UResourceBundle* gregorian) {
if (U_FAILURE(status)) {
return NULL;
}
- jstring eraU = env->NewString(era, eraLength);
- env->SetObjectArrayElement(eras, i, eraU);
- env->DeleteLocalRef(eraU);
+ ScopedLocalRef eraU(env, env->NewString(era, eraLength));
+ env->SetObjectArrayElement(eras, i, eraU.get());
}
return eras;
}
@@ -461,14 +453,12 @@ static jobjectArray getMonthNames(JNIEnv* env, UResourceBundle* gregorian, bool
if (U_FAILURE(status)) {
return NULL;
}
- jstring monthU = env->NewString(month, monthNameLength);
- env->SetObjectArrayElement(months, i, monthU);
- env->DeleteLocalRef(monthU);
+ ScopedLocalRef monthU(env, env->NewString(month, monthNameLength));
+ env->SetObjectArrayElement(months, i, monthU.get());
}
- jstring monthU = env->NewStringUTF("");
- env->SetObjectArrayElement(months, monthCount, monthU);
- env->DeleteLocalRef(monthU);
+ ScopedLocalRef monthU(env, env->NewStringUTF(""));
+ env->SetObjectArrayElement(months, monthCount, monthU.get());
return months;
}
@@ -509,9 +499,8 @@ static jobjectArray getWeekdayNames(JNIEnv* env, UResourceBundle* gregorian, boo
if(U_FAILURE(status)) {
return NULL;
}
- jstring dayU = env->NewString(day, dayNameLength);
- env->SetObjectArrayElement(weekdays, i + 1, dayU);
- env->DeleteLocalRef(dayU);
+ ScopedLocalRef dayU(env, env->NewString(day, dayNameLength));
+ env->SetObjectArrayElement(weekdays, i + 1, dayU.get());
}
return weekdays;
}