私の同僚と私はアプリケーションにいくつかのメモリ問題を抱えています。私たちが行ったディスカバリーの1つはデータベースから来たストリング値です(重複度が高い)は、実際には中止されていません。したがって重複した値がメモリに保持され、潜在的に大きな問題になる可能性があります。Java JDBCが文字列値を再利用していませんか?
たとえば、SQLiteデータベースと同じ文字列をクエリする単純なJDBCの例を次に示します。私はそれぞれのIDハッシュコードを表示し、それぞれが別のインスタンスであることを示します。
import java.sql.*;
public class Test {
public static void main(String[] args)
{
Connection connection = null;
try
{
// create a database connection
connection = DriverManager.getConnection("jdbc:sqlite:/C:/rexon_metals.db");
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SELECT REGION FROM CUSTOMER WHERE REGION = 'Southwest'");
while(rs.next())
{
String region = rs.getString("REGION");
System.out.println(region + ": " + System.identityHashCode(region));
}
}
catch(SQLException e)
{
// if the error message is "out of memory",
// it probably means no database file is found
System.err.println(e.getMessage());
}
finally
{
try
{
if(connection != null)
connection.close();
}
catch(SQLException e)
{
// connection close failed.
System.err.println(e);
}
}
}
}
OUTPUT:
Southwest: 405662939
Southwest: 653305407
Southwest: 1130478920
Southwest: 1404928347
しかし、私は明示的にString.intern()
メソッドを呼び出した場合、すべてのアイデンティティーハッシュコードは同じです。
String region = rs.getString("REGION").intern();
OUTPUT:
Southwest: 405662939
Southwest: 405662939
Southwest: 405662939
Southwest: 405662939
なぜJDBCは私のためにintern()
を呼び出すことはありませんでしょうか?これは、多くの重複したString
値がある場合に、開発者が行うことが期待されますか?これは頻繁に使用され、アプリケーションのセッション全体で持続されますか?
P.S. - 何百にもなる数百万の文字列値があります。これは手動のintern()コールを保証するものですか?
私はなぜあなたが驚いているのか分かりません。 '.intern()'がいつ役に立つかを判断するために、Javaランタイムが文字列を解析することを何も見たことがありません。特に、データベースクエリが呼び出されたときにこれを行うことができるので、確かに良い考えであると思われます。 – arcy
私は実際にそれについて考えているので、なぜ私が驚いているのか分かりません。私はJVMが私にとって魔法の最適化を行うと思っていました。今では、永続性がどのように発生しなければならないかを実際に検討しているので、なぜそれが必ずしも自動的に起こらないのか分かります。 – tmn
実際には、このような "魔法の"最適化があります:G1ガベージコレクタで使用できる '-XX:+ UseStringDeduplication'です。 – apangin