栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

使用easyexcel,在服务器上报 java.lang.ArrayIndexOutOfBoundsException: 0

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用easyexcel,在服务器上报 java.lang.ArrayIndexOutOfBoundsException: 0

项目场景:

使用easyexcel,在服务器上报 java.lang.ArrayIndexOutOfBoundsException: 0

java.lang.ArrayIndexOutOfBoundsException: 0
    at sun.font.CompositeFont.getSlotFont(CompositeFont.java:351)
    at sun.font.CompositeGlyphMapper.initMapper(CompositeGlyphMapper.java:81)
    at sun.font.CompositeGlyphMapper.(CompositeGlyphMapper.java:62)
    at sun.font.CompositeFont.getMapper(CompositeFont.java:409)
    at sun.font.CompositeFont.canDisplay(CompositeFont.java:435)
    at java.awt.Font.canDisplayUpTo(Font.java:2063)
    at java.awt.font.TextLayout.singleFont(TextLayout.java:470)
    at java.awt.font.TextLayout.(TextLayout.java:531)
    at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:275)
    at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.(AutoSizeColumnTracker.java:117)
    at org.apache.poi.xssf.streaming.SXSSFSheet.(SXSSFSheet.java:82)
    at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:658)
    at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:679)
    at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:90)
    at com.alibaba.excel.util.WorkBookUtil.createSheet(WorkBookUtil.java:66)

问题描述:

在本地测试Excel的导出是正常的,但是上传了服务器,通过Postman 测试发现了返回500,服务器报错


原因分析:

经过 远程链接服务器的Java程序 Debug 到 报错列表中的 :at sun.font.CompositeFont.getSlotFont(CompositeFont.java:351) 位置


根据Debug的提示判断是由 deferredInitialisation[slot] 引起的报错,Debug显示 deferredInitialisation 长度为 0、slot指为0

做个校验:

接下来让我们看看 deferredInitialisation这个数组的由来:

菜鸡的我 进过了一天的Debug 和 踩坑 终于是Debug到了,下面说重要的地方~~

1、java.awt.Font#getFont2D
private Font2D getFont2D() {
	// 用于检索当前平台的有效 FontManager 实例的工厂类。为 Linux、Solaris 和 Windows 提供了默认实现。
    FontManager fm = FontManagerFactory.getInstance(); // 从此处进入
    if (fm.usingPerAppContextComposites() &&
        font2DHandle != null &&
        font2DHandle.font2D instanceof CompositeFont &&
        ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
        return fm.findFont2D(name, style,
                                      FontManager.LOGICAL_FALLBACK);
    } else if (font2DHandle == null) {
        font2DHandle =
            fm.findFont2D(name, style,
                          FontManager.LOGICAL_FALLBACK).handle;
    }
    
    return font2DHandle.font2D;
}
2、sun/font/FontManagerFactory.java (优先执行静态代码块)
static {
	// 根据不同操作系统加载不同的 FontManager
    if (FontUtilities.isWindows) {
        DEFAULT_CLASS = "sun.awt.Win32FontManager";
    } else if (FontUtilities.isMacOSX) {
        DEFAULT_CLASS = "sun.font.CFontManager";
        } else {
        DEFAULT_CLASS = "sun.awt.X11FontManager";
        }
}
3、sun.font.FontManager#getInstance()
public static synchronized FontManager getInstance() {

    if (instance != null) {
        return instance;
    }

    AccessController.doPrivileged(new PrivilegedAction() {

        public Object run() {
            try {
                String fmClassName =
                        System.getProperty("sun.font.fontmanager",
                                           DEFAULT_CLASS);
                ClassLoader cl = ClassLoader.getSystemClassLoader();
                // 注册 通过静态代码块得到的 FontManager 看 步骤 4
                Class fmClass = Class.forName(fmClassName, true, cl);
                // 通过静态代码块得到的 FontManager,反射创建对象 
                instance =
                   (FontManager) fmClass.getDeclaredConstructor().newInstance();
            } catch (ReflectiveOperationException ex) {
                throw new InternalError(ex);

            }
            return null;
        }
    });

    return instance;
}
 

由于在远程Debug找到了原因,切远程Debug与本地代码经常对应不上,换至Windows上进行Debug,
故步骤 3 创建的FontManager为Win32FontManager

4、sun.awt.Win32FontManager(先执行静态代码块)
static {
	AccessController.doPrivileged(new PrivilegedAction() {
		public Object run() {
      		// 获取 EUDC 字体文件
			String eudcFile = getEUDCFontFile();
			if (eudcFile != null) {
			    try {
			        
			        eudcFont = new TrueTypeFont(eudcFile, null, 0,
			                                    true, false);
			    } catch (FontFormatException e) {
			    }
			}
			return null;
		}
  });
}
 
5、sun.font.SunFontManager#SunFontManager() 
protected SunFontManager() {
	// 这里就是加载系统字体的地方
    this.initJREFontMap();
    AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            File var1 = new File(SunFontManager.jreFontDirName + File.separator + "badfonts.txt");
            String var5;
            if (var1.exists()) {
                FileInputStream var2 = null;

                try {
                    SunFontManager.this.badFonts = new ArrayList();
                    var2 = new FileInputStream(var1);
                    InputStreamReader var3 = new InputStreamReader(var2);
                    BufferedReader var4 = new BufferedReader(var3);

                    while(true) {
                        var5 = var4.readLine();
                        if (var5 == null) {
                            break;
                        }

                        if (FontUtilities.debugFonts()) {
                            FontUtilities.getLogger().warning("read bad font: " + var5);
                        }

                        SunFontManager.this.badFonts.add(var5);
                    }
                } catch (IOException var8) {
                    try {
                        if (var2 != null) {
                            var2.close();
                        }
                    } catch (IOException var7) {
                    }
                }
            }

            if (FontUtilities.isLinux) {
                SunFontManager.this.registerFontDir(SunFontManager.jreFontDirName);
            }

            SunFontManager.this.registerFontsInDir(SunFontManager.jreFontDirName, true, 2, true, false);
            SunFontManager.this.fontConfig = SunFontManager.this.createFontConfiguration();
            if (SunFontManager.isOpenJDK()) {
                String[] var9 = SunFontManager.this.getDefaultPlatformFont();
                SunFontManager.this.defaultFontName = var9[0];
                SunFontManager.this.defaultFontFileName = var9[1];
            }

            String var10 = SunFontManager.this.fontConfig.getExtraFontPath();
            boolean var11 = false;
            boolean var12 = false;
            var5 = System.getProperty("sun.java2d.fontpath");
            if (var5 != null) {
                if (var5.startsWith("prepend:")) {
                    var11 = true;
                    var5 = var5.substring("prepend:".length());
                } else if (var5.startsWith("append:")) {
                    var12 = true;
                    var5 = var5.substring("append:".length());
                }
            }

            if (FontUtilities.debugFonts()) {
                PlatformLogger var6 = FontUtilities.getLogger();
                var6.info("JRE font directory: " + SunFontManager.jreFontDirName);
                var6.info("Extra font path: " + var10);
                var6.info("Debug font path: " + var5);
            }

            if (var5 != null) {
                SunFontManager.this.fontPath = SunFontManager.this.getPlatformFontPath(SunFontManager.noType1Font);
                if (var10 != null) {
                    SunFontManager.this.fontPath = var10 + File.pathSeparator + SunFontManager.this.fontPath;
                }

                if (var12) {
                    SunFontManager.this.fontPath = SunFontManager.this.fontPath + File.pathSeparator + var5;
                } else if (var11) {
                    SunFontManager.this.fontPath = var5 + File.pathSeparator + SunFontManager.this.fontPath;
                } else {
                    SunFontManager.this.fontPath = var5;
                }

                SunFontManager.this.registerFontDirs(SunFontManager.this.fontPath);
            } else if (var10 != null) {
                SunFontManager.this.registerFontDirs(var10);
            }

            if (FontUtilities.isSolaris && Locale.JAPAN.equals(Locale.getDefault())) {
                SunFontManager.this.registerFontDir("/usr/openwin/lib/locale/ja/X11/fonts/TT");
            }
			
			// 初始化 CompositeFont
            SunFontManager.this.initCompositeFonts(SunFontManager.this.fontConfig, (ConcurrentHashMap)null);
            return null;
        }
    });
    boolean var1 = (Boolean)AccessController.doPrivileged(new PrivilegedAction() {
        public Boolean run() {
            String var1 = System.getProperty("java2d.font.usePlatformFont");
            String var2 = System.getenv("JAVA2D_USEPLATFORMFONT");
            return "true".equals(var1) || var2 != null;
        }
    });
    if (var1) {
        this.usePlatformFontMetrics = true;
        System.out.println("Enabling platform font metrics for win32. This is an unsupported option.");
        System.out.println("This yields incorrect composite font metrics as reported by 1.1.x releases.");
        System.out.println("It is appropriate only for use by applications which do not use any Java 2");
        System.out.println("functionality. This property will be removed in a later release.");
    }

}
6、sun.font.SunFontManager#registerCompositeFont()
protected void registerCompositeFont(String var1, String[] var2, String[] var3, int var4, int[] var5, int[] var6, boolean var7) {
   CompositeFont var8 = new CompositeFont(var1, var2, var3, var4, var5, var6, var7, this);
    this.addCompositeToFontList(var8, 2);
    synchronized(this.compFonts) {
        this.compFonts[this.maxCompFont++] = var8;
    }
}
7、sun.font.CompositeFont#CompositeFont()
public CompositeFont(String name, String[] compFileNames,
                         String[] compNames, int metricsSlotCnt,
                         int[] exclRanges, int[] maxIndexes,
                         boolean defer, SunFontManager fm) {

    handle = new Font2DHandle(this);
    fullName = name;
    componentFileNames = compFileNames;
    componentNames = compNames;
    if (compNames == null) {
        numSlots = componentFileNames.length;
    } else {
        numSlots = componentNames.length;
    }
    
     numSlots = (numSlots <= 254) ? numSlots : 254;

    numMetricsSlots = metricsSlotCnt;
    exclusionRanges = exclRanges;
    maxIndices = maxIndexes;

    if (fm.getEUDCFont() != null) {
        int msCnt = numMetricsSlots;
        int fbCnt = numSlots - msCnt;
        numSlots++;
        if (componentNames != null) {
            componentNames = new String[numSlots];
            System.arraycopy(compNames, 0, componentNames, 0, msCnt);
            componentNames[msCnt] = fm.getEUDCFont().getFontName(null);
            System.arraycopy(compNames, msCnt,
                             componentNames, msCnt+1, fbCnt);
        }
        if (componentFileNames != null) {
            componentFileNames = new String[numSlots];
            System.arraycopy(compFileNames, 0,
                              componentFileNames, 0, msCnt);
            System.arraycopy(compFileNames, msCnt,
                              componentFileNames, msCnt+1, fbCnt);
        }
        components = new PhysicalFont[numSlots];
        components[msCnt] = fm.getEUDCFont();
        // 此时已经找到了 那个导致抛出异常数组的赋值
        deferredInitialisation = new boolean[numSlots];
        if (defer) {
            for (int i=0; i
                deferredInitialisation[i] = true;
            }
        }
    } else {
        components = new PhysicalFont[numSlots];
        deferredInitialisation = new boolean[numSlots];
        if (defer) {
            for (int i=0; i
                deferredInitialisation[i] = true;
            }
        }
    }

    fontRank = Font2D.FONT_CONFIG_RANK;

    int index = fullName.indexOf('.');
    if (index>0) {
        familyName = fullName.substring(0, index);
        
        if (index+1 < fullName.length()) {
            String styleStr = fullName.substring(index+1);
            if ("plain".equals(styleStr)) {
                style = Font.PLAIN;
            } else if ("bold".equals(styleStr)) {
                style = Font.BOLD;
            } else if ("italic".equals(styleStr)) {
                style = Font.ITALIC;
            } else if ("bolditalic".equals(styleStr)) {
                style = Font.BOLD | Font.ITALIC;
            }
        }
    } else {
        familyName = fullName;
    }
}

解决方案: 使用Root权限启动 给服务器添加字体: 1、查看中文字体
fc-list :lang=zh
2、安装字体
yum -y install fontconfig	#安装字体库
yum -y install ttmkfdir	mkfontscale	#安装字体索引信息

可拷贝Windows的字体目录:C:WindowsFonts

3、linux字体目录:/usr/share/fonts,建议创建一个目录mkdir chinese 放中文字体 4、把字体上传到/usr/share/fonts/chinese目录 5、然后在/usr/share/fonts/chinese执行命令,生成字库索引信息
mkfontscale
mkfontdir
6、更新字体缓存
fc-cache
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号