java字符串太长会有什么异常,【转】Error,java对常量池来说字符串xxx的UTF8表示过长的解决及其理解...

做项目,客户端这里自己模拟json数据时,一时没忍住搞得json字符串太长了(idea上大概有600多行吧),这个问题就蹦出来了。老方法直接google、百度然后看到一堆有关String 字符串常量池字符最大限制的文章,这些前辈都是从jvm的运行时常量池的常量表占的内存数,从原理上讲解了常量池所能容纳的最大字符数。对于不了解jvm的同学来说,啥无符号数、有符号数、u1、u2之类的看着看着就懵逼了。俗话说学而不思则罔,这里我就从常量池和内存区域的角度来简单分析下自己的观点。相对jvm的那套理论感觉更容易使人接受。

一、背景

9c900d02adc4815a078dd4a1dd0cad39.png

/**

* Created by sunnyDay on 2019/11/19 17:31

*

* double check

*/

public class Jsons {

private volatile static Jsons instance;

private Jsons() {

}

public static Jsons getInstance() {

if (instance == null) {

synchronized ("lock") {

if (instance == null) {

instance = new Jsons();

}

}

}

return instance;

}

public String getConstellationTestJson(){

return "很长的json,粘贴的下图json文件的字符串"

}

}

public class Test {

public static void main(String[] args) {

// 编译时直接报错

System.out.println(Jsons.getInstance().getConstellationTestJson());

}

}

fd4c8e1f73a14c6a113a269a4d94431a.png

如上:就是一个工具类,提供json字符串,为了演示我单独抽出来放idea中跑了下。

二、字符串String的最大长度

理论解析:

传送门

三、我的理解及其解决方案

理论性的东西前辈们都总结的差不多了,这里就添加下个人理解。及其解决方案。

1、首先理解下jvm方法区的运行时池

好处:

常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。

注意点:

1、java中基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。这里就就只说字符传常量池相关。

2、java中以双引号引住的内容就是字符创常量,编译时就会吧双引号引的内容放入字符创常量池。

2、字符创常量池的实战参考(一定要看)

String stra = "abcd"; // 对象存储在常量池中

String strb = new String("abcd");// new 就是在堆中分配了新的地址

System.out.println(stra==strb);//false

String str1 = "str";

String str2 = "ing";

String str3 = "str" + "ing";

String str4 = str1 + str2; //对于字符串变量的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,其属于在运行时创建的字符串,具有独立的内存地址,所以不引用自同一String对象。

System.out.println("string" == "str" + "ing");// true 只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入常量池中

System.out.println(str3 == str4);//false

String str5 = "string";

System.out.println(str3 == str5);//true

注意点:

1、+号连接的对象引用

2、+号链接的字符串常量

3、解决方案

不让放那么多,这里放不了我们不放这里或者这里放少点。不ojbk了。太聪明了嘿嘿嘿!!!

(1)错误解决方式

public String getConstellationTestJson(){

return "很长的json一半"+"很长的json一半";

}

这里+号拼接的结果还是会放进常量池的。参考实战。

(2)正确解决方式

```java

public String getConstellationTestJson(){

String s1 = "很长的json一半"; //内容放常量池

String s2 = "很长的json一半"; // 内容放常量池

return s1+s2; // 结果具有了新的内存地址(堆中)

}

解决,s1+s2的结果会放入新的内存地址中,参考上文实战。

(3)正确解决 使用new String 拆分拼接

(4)使用StringBuild#StringBuffer 拆分拼接

(5)通过文件读取(这里使用安卓的assets为例子)

private String getAssetsData() {

String result = "";

try {

InputStream mAssets = getAssets().open("dream.json");

int lenght = mAssets.available();

byte[] buffer = new byte[lenght];

mAssets.read(buffer);

mAssets.close();

result = new String(buffer, StandardCharsets.UTF_8); // 关键之处

return result;

} catch (IOException e) {

e.printStackTrace();

return result;

}

}

4、感悟

只要堆的内存不满,或者拆分的子字符串满足常量池大小,就基本没啥问题了。

5、推荐参考:java内存区域与内存溢出异常的常量池部分内容

————————————————

版权声明:本文为CSDN博主「dev晴天」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_38350635/article/details/103495951

【JVM】Java 8 中的常量池、字符串池、包装类对象池

1 - 引言 2 - 常量池 2.1 你真的懂 Java的“字面量”和“常量”吗? 2.2 常量和静态/运行时常量池有什么关系?什么是常量池? 2.3 字节码下的常量池以及常量池的加载机制 2.4 是 ...

Java String 常量池理解

String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...

String类、常量池、字符串比较

String类.常量池.字符串比较 一:String类           1.String类又称作不可变字符序列           2.String位于java.lang包中,Java程序默认导入 ...

常量池之字符串常量池String.intern()

运行时常量池是方法区(PermGen)的一部分. 需要提前了解: 1. JVM内存模型. 2. JAVA对象在JVM中内存分配 常量池的好处 常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现 ...

JVM 常量池、运行时常量池、字符串常量池

常量池: 即class文件常量池,是class文件的一部分,用于保存编译时确定的数据. 保存的内容如下图: D:\java\test\out\production\test>javap -ver ...

Java基础-常量池

在class文件中,“常量池”是最复杂也最值得关注的内容. Java是一种动态连接的语言,常量池的作用非常重要,常量池中除了包含代码中所定义的各种基本类型(如int.long等等)和对象型(如Stri ...

java基础知识回顾之---java String final类 容易混淆的java String常量池内存分析

/** *   栈(Stack) :存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放  在常量池中). 堆(heap):存 ...

Java - 包装类 常量池

概述: 在Java中存在一些基本数据类型,这些基本数据类型变量,不能像其他对象一样调用方法,属性.... 一些情况下带来一些问题,包装类就是为了解决这个问题而出现 包装类可以使得这些基础数据类型,拥有 ...

Java Integer常量池——IntegerCache内部类

个人理解,不喜勿喷,欢迎指正. 首先看下面这段代码,猜一下输出结果是什么 Integer a = 10; Integer b = 10; System.out.println(a == b); a = ...

随机推荐

【NodeJS 学习笔记01】不学就老了

前言 再不学nodeJs,我们就老了......在HTML5大浪袭来的时候,很多先辈就开始了NodeJs之旅,而那时我还在做服务器端的程序后来转成前端,和梯队的距离已经很大了,因为我会服务器端语言,还 ...

HDU5806 NanoApe Loves Sequence Ⅱ (BestCoder Round #86 C)二分

分析:大于等于m的变成1,否则变成0,预处理前缀和,枚举起点,找到第一个点前缀和大于m即可 找第一个点可以二分可以尺取 #include #include

String转float

float mTotalhour = Float.parseFloat(mTotalHourEt.getText().toString().trim());

cnpm下载包与npm版本不一致的问题解决

参考链接:https://www.jianshu.com/p/949b4e0ae190

面向对象的JavaScript-小结

Javascript中的类 类是对象的模板,用于创建共享一系列属性和方法的类似对象. 使用new关键字调用函数,可以创建对象实例. function Accommodation(){}; var ho ...

Shell-14--awk

awk ' 条件1{ 动作1} 条件2{动作2}...' 文件名 awk处理数据是 先读取第一行 然后再去处理 printf 不会加入换行符,需要手动加入 print 会自动加换行 begin 是在后 ...

gulp 编译es6 探究

1.gulp配置: var gulp = require('gulp') var fs = require("fs") var babelify = require('babeli ...

hdu 4983 欧拉函数

http://acm.hdu.edu.cn/showproblem.php?pid=4983 求有多少对元组满足题目中的公式. 对于K=1的情况,等价于gcd(A, N) * gcd(B, N) = ...

JAVA 并发编程-多个线程之间共享数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值