我有这个用 Java 制作的自定义解析器,我想将 3.6 GB 的 Json 导出到 Sql Oracle 数据库中。对于 8MB 的示例 Json,导入工作正常。但是当我尝试解析整个 3.6 GB JSON 时,出现了一些内存问题,即 java.lang.OutOfMemoryError
我已经使用 -Xmx5000m 为此分配了 5 GB 的内存。我的笔记本电脑有足够的内存。
如您所见,我还有剩余内存。是否因为 CPU 而发生此错误?
更新: Json 表示来自 Free Code Camp 的数据:https://medium.freecodecamp.com/free-code-camp-christmas-special-giving-the-gift-of-data-6ecbf0313d62#.7mjj6abbg
数据看起来像这样:
[ { “名称”:“Waypoint:向 HTML 元素问好”, “完成日期”:1445854025698, “解决方案”:“
Hello World
\n” } ]正如我所说,我已经尝试使用具有相同数据的 8MB 样本 Json 进行解析,并且成功了。那么代码真的是这里的问题吗?
代码如下
enter code here
public class MainParser {
public static void main(String[] args) {
//Date time;
try {
BufferedReader br = new BufferedReader(
new FileReader("output.json")); //destination to json here
Gson gson = new Gson();
Type collectionType = new TypeToken<List<List<Tasks>>>() {
}.getType();
List<List<Tasks>> details = gson.fromJson(br, collectionType);
DBConnect connection = new DBConnect("STUDENT","student");
connection.connect();
for (int person=0;person<details.size();person++)
{
for (int task = 0; task < details.get(person).size(); task++)
{
connection.insert_query(person + 1,
task + 1,
details.get(person).get(task).getName(),
(details.get(person).get(task).getCompletedDate()/1000),
details.get(person).get(task).getSolution());
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
这是 insert_query 方法:
enter code here
public void insert_query(int person_id, int task_id, String taskName, double date, String solution) throws SQLException {
Statement stmt = conn.createStatement();
try {
String query = "INSERT INTO FreeCodeCamp VALUES(?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(query);
ps.setInt(1,person_id);
ps.setInt(2,task_id);
ps.setString(3,taskName);
ps.setDate(4,null);
ps.setString(5,solution);
/*stmt.executeUpdate("INSERT INTO FreeCodeCamp VALUES("
+ person_id + ","
+ task_id + ","
+ "'" + taskName + "',"
+ "TO_TIMESTAMP(unix_ts_to_date(" + date + "),'YYYY-MM-DD HH24:MI:SS'),"
+ "'" + solution + "')");
stmt.close();*/
ps.execute();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
请您参考如下方法:
解析 JSON(或任何东西,就此而言)不会占用与原始文件大小相同的内存。
表示一个对象的每个 JSON 字符串 block 将成为一个对象,向已加载的 JSON 添加内存。如果您使用某种流来解析它,您仍然会增加内存,但会少得多(您不会将整个 3.6GB 文件保存在内存中)。
尽管如此,一个对象比字符串需要更多的内存来表示。如果您有一个数组,它可能会被解析为一个列表,那么该列表就会有开销。将该开销乘以您在 JSON 中拥有的实例(相当多,在一个 3.6 GB 的文件中),您最终得到的东西占用的内存远远超过 3.6GB。
但是如果你想将它解析为一个流,并处理每条记录,然后丢弃它,你可以这样做。在这两种使用流的情况下,您都需要一个组件来解析 JSON 并让您处理每个解析的对象。如果您知道结构,那么自己编写一个结构可能会更容易。
希望对您有所帮助。