Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

Prism's Glyphcache management throws ArrayIndexOutOfBoundsExceptions on ListView changes #287

Closed
Tristan971 opened this issue Nov 15, 2018 · 60 comments
Labels
bug Something isn't working

Comments

@Tristan971
Copy link
Contributor

Hello, I've been having prism issues pop up on Linux lately (as in, doesn't happen on Windows implementation at all)

System info

  • Linux Kernel 4.14
  • Happens on both intel and nvidia drivers
  • GTK 3.24 and 2.24 (test with and without -Djdk.gtk.version=2 without any difference)
  • DE : Budgie Desktop (GTK3 based)
  • Running on X11 (so no Wayland-related issue here)

Java/Maven/OpenJFX info

Apache Maven 3.6.0 (NON-CANONICAL_2018-11-06T03:14:22+01:00_root; 2018-11-06T02:14:22Z)
Maven home: /opt/maven
Java version: 11.0.1, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-11-openjdk
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.14.80-1-manjaro", arch: "amd64", family: "unix"
  • OpenJFX 11.0.1 from maven

Failing component

It seems to be when using a ListView that overrides the graphic property of its cells to render a full node in each cell (basically having a list of nodes rather than of only primitive-wrapping cells/simple controls).
When the computation of some of the elements is executed on resizing of window, or on adding more elements to the list (which incurs recomputation of stuff like scroll bar size), some assertion is failing.

What happens

The UI freezes while ArrayIndexOutofBoundsExceptions are being spilled in hundreds

  • Before corruption:
    before

  • After:
    after

  • The exceptions I get (all the same):

java.lang.ArrayIndexOutOfBoundsException: Index -9 out of bounds for length 32
	at com.sun.prism.impl.GlyphCache.getCachedGlyph(GlyphCache.java:246)
	at com.sun.prism.impl.GlyphCache.render(GlyphCache.java:148)
	at com.sun.prism.impl.ps.BaseShaderGraphics.drawString(BaseShaderGraphics.java:2101)
	at com.sun.javafx.sg.prism.NGText.renderText(NGText.java:312)
	at com.sun.javafx.sg.prism.NGText.renderContent2D(NGText.java:270)
	at com.sun.javafx.sg.prism.NGShape.renderContent(NGShape.java:261)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
	at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964))

	... (tens of times the same cycle of render -> doRender -> renderContent)

	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
	at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
	at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
	at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:321)
	at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
	at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
	at java.base/java.lang.Thread.run(Thread.java:834)
  • Which happens here precisely:
private GlyphData getCachedGlyph(int glyphCode, int subPixel) {
    int segIndex = glyphCode >> SEGSHIFT;
    int subIndex = glyphCode % SEGSIZE;
    segIndex |= (subPixel << SUBPIXEL_SHIFT);
    GlyphData[] segment = glyphDataMap.get(segIndex);
    if (segment != null) {
        if (segment[subIndex] != null) {
            return segment[subIndex];  <-------------------------- here's the exception
        }
    } else {
        segment = new GlyphData[SEGSIZE];
        glyphDataMap.put(segIndex, segment);
    }

Overall I do not have an idea of why it happens and it doesn't seem to be easily reproducible so as for a locally reproducible way you can use branch develop of https://github.com/Tristan971/Lyrebird/ (lyrebird submodule is the runnable app) and just scroll through a twitter timeline (in my experience you need to reach the end of the timeline so that the app actually has to fetch older tweets and plug them in the item list of the ListView.

Will try to inquire it on my own as well, but if someone had an idea it would be pretty helpful.

Thank you

@kevinrushforth
Copy link
Collaborator

kevinrushforth commented Nov 16, 2018

Given the error this seems clearly to be a JavaFX bug. Can you run it with the following flags?

java -Dprism.verbose=true -Djdk.gtk.verbose=true

@eugener eugener added the bug Something isn't working label Nov 18, 2018
@Tristan971
Copy link
Contributor Author

Tristan971 commented Nov 19, 2018

Unfortunately I believe the logs do not give much more info on the actual error, but at least they do print a few status infos.

Highlights I gathered (or see full log ) :

Prism pipeline init order: es2 sw 
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
	succeeded.
GLFactory using com.sun.prism.es2.X11GLFactory
(X) Got class = class com.sun.prism.es2.ES2Pipeline
Initialized prism pipeline: com.sun.prism.es2.ES2Pipeline
checking GTK version 2
trying GTK library libgtk-x11-2.0.so.0
using GTK library version 2 set libgtk-x11-2.0.so.0
Glass GTK library to load is glassgtk2
loaded g_settings_schema_source_get_default
loaded g_settings_schema_source_lookup
loaded g_settings_schema_has_key
found schema 'org.gnome.desktop.interface' and key 'scaling-factor'
loaded g_settings_schema_unref
found schema 'org.gnome.desktop.interface' and key 'scaling-factor'
Maximum supported texture size: 16384
Maximum texture size clamped to 4096
Non power of two texture support = true
Maximum number of vertex attributes = 16
Maximum number of uniform vertex components = 16384
Maximum number of uniform fragment components = 16384
Maximum number of varying components = 128
Maximum number of texture units usable in a vertex shader = 32
Maximum number of texture units usable in a fragment shader = 32
Graphics Vendor: Intel Open Source Technology Center
       Renderer: Mesa DRI Intel(R) HD Graphics 530 (Skylake GT2) 
        Version: 3.0 Mesa 18.2.5
 vsync: true vpipe: true

...

ES2ResourceFactory: Prism - createStockShader: FillPgram_Color.frag
ES2ResourceFactory: Prism - createStockShader: Solid_TextureFirstPassLCD.frag
ES2ResourceFactory: Prism - createStockShader: Solid_TextureSecondPassLCD.frag
ES2ResourceFactory: Prism - createStockShader: Solid_TextureRGB.frag
ES2ResourceFactory: Prism - createStockShader: FillCircle_Color.frag
PPSRenderer: scenario.effect - createShader: Blend_SRC_IN
ES2ResourceFactory: Prism - createStockShader: DrawCircle_Color.frag

...

ES2ResourceFactory: Prism - createStockShader: Mask_TextureSuper.frag
java.lang.ArrayIndexOutOfBoundsException: Index -9 out of bounds for length 32
	at com.sun.prism.impl.GlyphCache.getCachedGlyph(GlyphCache.java:332)
	at com.sun.prism.impl.GlyphCache.render(GlyphCache.java:148)
        (stacktrace cycle repeating itself as in the previous message)

here somehow the UI fixes itself for a brief moment, then any further interaction with it yields us broken state again with output :

ES2ResourceFactory: Prism - createStockShader: FillRoundRect_Color.frag
ES2ResourceFactory: Prism - createStockShader: FillPgram_LinearGradient_PAD.frag
new alphas with length = 4096
ES2ResourceFactory: Prism - createStockShader: Texture_Color.frag
PPSRenderer: scenario.effect - createShader: LinearConvolveShadow_4
ES2ResourceFactory: Prism - createStockShader: Texture_LinearGradient_PAD.frag
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
... (arrayindexoutofbounds forever whenever interacting with UI)

@kevinrushforth
Copy link
Collaborator

Perhaps the most interesting line is:

Renderer: Mesa DRI Intel(R) HD Graphics 530 (Skylake GT2)

I don't know that we have too much experience with this chipset, although it seems a little odd that differences in graphics HW would cause an AIOOBE in the font rendering code.

@Tristan971
Copy link
Contributor Author

If I remember correctly the same happened with the Nvidia renderer on my home box though, so it might not be it indeed.

Will check and send through the according logs.

@Tristan971
Copy link
Contributor Author

Tristan971 commented Nov 21, 2018

So I just checked at home, using totally different CPU/GPU system combination (AMD x Nvidia instead of Intel²) and get the same results (interestingly, I get the errors consistently instantaneously, instead of after tinkering for a few seconds).

Also same behavior with GTK2 (by forcing it with -Djdk.gtk.version=2) or GTK3

Earlier line becomes

Graphics Vendor: NVIDIA Corporation
       Renderer: GeForce GTX 1080/PCIe/SSE2
        Version: 4.6.0 NVIDIA 410.78

See here for trimmed logs (full_logs attached as before)

<pre-javafx app stuff>

Prism pipeline init order: es2 sw 
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
	succeeded.
GLFactory using com.sun.prism.es2.X11GLFactory
(X) Got class = class com.sun.prism.es2.ES2Pipeline
Initialized prism pipeline: com.sun.prism.es2.ES2Pipeline
checking GTK version 3
trying GTK library libgtk-3.so.0
using GTK library version 3 set libgtk-3.so.0
Glass GTK library to load is glassgtk3
loaded gdk_x11_display_set_window_scale
loaded g_settings_schema_source_get_default
loaded g_settings_schema_source_lookup
loaded g_settings_schema_has_key
found schema 'org.gnome.desktop.interface' and key 'scaling-factor'
loaded g_settings_schema_unref
Maximum supported texture size: 32768
Maximum texture size clamped to 4096
Non power of two texture support = true
Maximum number of vertex attributes = 16
Maximum number of uniform vertex components = 4096
Maximum number of uniform fragment components = 4096
Maximum number of varying components = 124
Maximum number of texture units usable in a vertex shader = 32
Maximum number of texture units usable in a fragment shader = 32
Graphics Vendor: NVIDIA Corporation
       Renderer: GeForce GTX 1080/PCIe/SSE2
        Version: 4.6.0 NVIDIA 410.78
 vsync: true vpipe: true

<app start-up>

ES2ResourceFactory: Prism - createStockShader: FillPgram_Color.frag
ES2ResourceFactory: Prism - createStockShader: Texture_Color.frag
ES2ResourceFactory: Prism - createStockShader: Solid_TextureRGB.frag
ES2ResourceFactory: Prism - createStockShader: FillCircle_Color.frag
PPSRenderer: scenario.effect - createShader: Blend_SRC_IN
ES2ResourceFactory: Prism - createStockShader: DrawCircle_Color.frag
ES2ResourceFactory: Prism - createStockShader: Mask_TextureSuper.frag
ES2ResourceFactory: Prism - createStockShader: FillRoundRect_Color.frag
ES2ResourceFactory: Prism - createStockShader: FillPgram_LinearGradient_PAD.frag
new alphas with length = 4096
PPSRenderer: scenario.effect - createShader: LinearConvolveShadow_4
ES2ResourceFactory: Prism - createStockShader: Texture_LinearGradient_PAD.frag
java.lang.ArrayIndexOutOfBoundsException: Index -23 out of bounds for length 32
	at com.sun.prism.impl.GlyphCache.getCachedGlyph(GlyphCache.java:332)
	at com.sun.prism.impl.GlyphCache.render(GlyphCache.java:148)
	...

@kevinrushforth
Copy link
Collaborator

At this point I don't have any ideas, except that you might want to check that all accesses to all live nodes are done from the JavaFX Application thread. We will need a standalone test program that reproduces it in order to do anything more.

@Tristan971
Copy link
Contributor Author

Will look into making one, just hoped the need would not be there as I'm getting those custom listview through somewhat unholy abuse of cell properties and a lot of it is not on the JFX thread on the data-side so it might not be trivial to reproduce... Anyway, will let you know once I have a minimal version of it.

@trixon
Copy link

trixon commented Nov 24, 2018

I just noted the same problem in two of my programs. Google led me here and thank you for pointing me to the ListView and custom list cell rendering.

I was able to track it down to the usage of Unicode characters and by removing them in the following commit I got the functionality back, without the nice looking glyphs.
trixon/mapollage@833624e

My list view used to look like this
alt tag

@Tristan971
Copy link
Contributor Author

Tristan971 commented Nov 24, 2018

Oh that is actually a pretty great find!
Unfortunately, I can't really remove unicode support as my app shows tweets and people do indeed use unicode characters (i.e. emojis) there.

I wonder if it's not an issue with these special characters being actually multiple code points for example?
Might be able to provide a test case more easily that way...


Edit : Also if I'm not wrong you're using KDE, so it's not only a Gnome-based issue.
Had reproduced it personally on both Gnome 3, Budgie and Awesome as for environments.

@trixon
Copy link

trixon commented Nov 24, 2018

Yes, it's KDE, Manjaro for me too (well NetRunner Rolling actually).

@Tristan971
Copy link
Contributor Author

Didn't try on a non-arch base. Would be worth testing if you have a ubuntu base somewhere as it could be stuff that fontconfig does not automatically set-up that javafx assumes?

@johanvos
Copy link
Collaborator

Seems you are closing in on the root cause. It would help if someone has a concrete reproducible code snippet?

@trixon
Copy link

trixon commented Nov 28, 2018

Ok, here we go!

`public class UnicodeListViewTest extends Application {

@Override
public void start(Stage stage) {

    StackPane root = new StackPane();
    ListView<String> listView = new ListView<>();
    listView.getItems().addAll("a", "b", "c");
    listView.getItems().add("🖉"); //Remove this row to make it work.
    listView.getItems().add("d");
    root.getChildren().add(listView);

    Scene scene = new Scene(root, 300, 250);

    stage.setTitle("Prism's Glyphcache");
    stage.setScene(scene);
    stage.show();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

}
`

@Tristan971
Copy link
Contributor Author

Oh I didn't realize it was not necessary to even toy with cells' graphics properties to get it to fail.
Thank you very much for the snippet!

@jonathonf
Copy link

jonathonf commented Nov 28, 2018

Just closing a loop because this was asked about on the Manjaro forum too.

With this snippet:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class UnicodeListViewTest extends Application {

	@Override
	public void start(Stage stage) {

		StackPane root = new StackPane();
		ListView<String> listView = new ListView<>();
		listView.getItems().addAll("a", "b", "c");
		listView.getItems().add("🖉"); //Remove this row to make it work.
		listView.getItems().add("d");
		root.getChildren().add(listView);

		Scene scene = new Scene(root, 300, 250);

		stage.setTitle("Prism's Glyphcache");
		stage.setScene(scene);
		stage.show();
	}

	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		launch(args);
	}

}

and compiling with

$ pacman -Q java-openjfx jdk8-openjdk
java-openjfx 8.u172-2
jdk8-openjdk 8.u192-1

$ javac -version
javac 1.8.0_192

$ java -version
openjdk version "1.8.0_192"
OpenJDK Runtime Environment (build 1.8.0_192-b26)
OpenJDK 64-Bit Server VM (build 25.192-b26, mixed mode)

$ javac UnicodeListViewTest.java
$ java UnicodeListViewTest

it works fine for me:

unicodelistviewtest

@Tristan971
Copy link
Contributor Author

Tristan971 commented Nov 28, 2018

The fact that it works here is fairly independent of the set-up for which I reported the issue (OpenJDK 11 + OpenJFX 11 vs OpenJDK 8 + OpenJFX 8) so although it is nice, I'm not sure what to really make of it.

That said if using OpenJFX 8 works, it means that the issue is probably a regression between 8 and 11.
Given that I have had not encountered this issue using Oracle's JavaFX 10 implementation (I reckon OpenJFX is basically the Oracle impl extracted though?), it might specifically be happening since version 11.

Interesting that the thread over there mentions no issues on non-arch distros. Might indeed be some fontconfig madness going on...

@trixon
Copy link

trixon commented Nov 29, 2018

I'm sorry, I failed to mention that I'm using Java 8. I have this problem with OpenJDK 8 + OpenJFX 8 and with Oracle's JDK8. I do however have Java 11 installed, but (open)jdk-8 is selected with the command archlinux-java

I created the following ant based Apache NetBeans project:
https://github.com/trixon/UnicodeListViewTest

@johanvos
Copy link
Collaborator

While it doesn't crash for me, I see something strange when I add debug information in GlyphCache.getCachedGlyph:
for the special character, the glyphcode = 788537807
For all other characters, the glyphcode is much lower (e.g. 68, 69, 70,...)
Since the AIOB shows the index is negative, and the index is glyphCode % 32 in some cases glyphCode seems to be negative.

@kevinrushforth
Copy link
Collaborator

@prrace do you have any thoughts on this?

@klausahrenberg
Copy link

I have the same issue. Rendering in listview with serveral unicode glyphs failed. This bug is filed here: https://bugs.openjdk.java.net/browse/JDK-8189092 - but still unresolved and Priority "minor". However, the root cause is explained there: "Somewhere glyph code values have overflowed such that we are storing a negative glyph code and this results in a negative index into an array."

@bourgesl
Copy link
Contributor

bourgesl commented Dec 11, 2018 via email

@kevinrushforth
Copy link
Collaborator

@bourgesl Thanks for offering to fix this. Can you file the JBS bug?

@bourgesl
Copy link
Contributor

I assigned JDK-8189092 to me, as I thought it was related to the same problem, I will have a look soon.
Maybe I did not follow the thread carefully, so I will read it again completely.
If needed, I will file another JBS bug, once my ideas are clearer.

@bourgesl
Copy link
Contributor

Hi,
I read both this thread (linux issue) and JDK-8189092 and I am a bit lost.
GlyphCache seems having a least 2 bugs...

Could someone make a synthetic summary of problems and reproducer codes ?

I will then work on fixing GlyphCache (newbie) during my holidays.

Thanks

@klausahrenberg
Copy link

I still think, the JDK-8189092 is related to the problem in this thread also. There is an issue with GlyphCache with 2 parts:

  1. Why is there a negative index for accessing the glyph cache, this case should not be possible. To find the root cause for this, is maybe not so easy (JDK-8189092 gives an idea). My researches today showed some troubles of JavaFX components with handling of CodePoints in Strings (e.g. for Emojis) - which results in ugly strings at Windows, but in Linux the whole program crashes (example below).
  2. If an error during accessing the glyph cache occurs, the JavaFX program is completely crashing (graphics failure and also no reactions at user inputs anymore). Accessing the cache with invalid indices should be fixed easily and would help a lot.

My observations today. Sorry, I don't have a deeper knowledge about Strings in UTF-16 and UTF-32. I only recognize that Strings which have special characters included (e.g. emojies or other), crashes text components in JavaFX - always with this Exception (only the negative index is not constant):

java.lang.ArrayIndexOutOfBoundsException: -11
    at javafx.graphics/com.sun.prism.impl.GlyphCache.getCachedGlyph(GlyphCache.java:332)
    at javafx.graphics/com.sun.prism.impl.GlyphCache.render(GlyphCache.java:148)

I tried this on Linux (Antergos) with JDK-9 and also with OpenJDK/OpenJFX-12-ea. The following JavaFX app crashes reproducable with the exception above and is (one) reason for the non-working ListView described in this thread:

public void start(Stage primaryStage) {
    //Create an Emoji
    char[] ca = new char[]{0xF0, 0x9F, 0x92, 0xB8};        
    String s = "Emoji: " + String.valueOf(ca);                
    //Create a textField that should display the prepared String
    TextField textField = new TextField();                                
    textField.setText(s);
    primaryStage.setScene(new Scene(new StackPane(textField)));                
    primaryStage.show();                
}

BUT: It crashes only in Linux in my case. I tried this with Windows10/JDK11 - the result is ugly, the unknown chars are displayed as a rectangle and also number of chars is wrong, but the app is not crashing at least.

Thanks a lot for any kind of solution. However, don't destroy your holiday because of this.

@bourgesl
Copy link
Contributor

@klausahrenberg thanks for your answer.
As I work on linux, I will first focus on linux issues (later I can test / debug on windows ...)

I will try reproducing the issue on my work-station and if it really fails, I will spend some time (when possible) on fixing the bug, I expect it will be not too complicated as I never looked at this JavaFX aspect (GlyphCache ...)
Please, do not expect me to fix it promptly (no SLA), it is just on best effort basis by an indie dev (no support contract).
If @prrace or @kevinrushforth could answer my possible questions or give me directions, that would be great.

@kevinrushforth
Copy link
Collaborator

The fix for #125, which was just merged, won't fix the exception on Linux, since that fix was in Windows-specific code.

@bourgesl
Copy link
Contributor

bourgesl commented Feb 1, 2019

Interesting, maybe fontconfig tuning could explain why returned glyphcode are different between linux distros...
Maybe we should compare what returns fc-match for this font:
$ fc-match --verbose Sans

@johanvos
Copy link
Collaborator

johanvos commented Feb 2, 2019

The problem is most likely due to something similar as #125 where a wrong conversion (e.g. an int being cut into a short) creates a negative index. As long as the number is small, the conversions will go fine.

@aditsu
Copy link

aditsu commented May 3, 2019

Is there any update on this? I've just hit this problem too.
I did some debugging with the above example code, and found that the issue starts in CompositeGlyphMapper.compositeGlyphCode. The slot is 144, and shifting left by 24 makes it negative. This might actually be expected, since afterwards it goes through LogicalFont.getAdvance which breaks it apart with >>> and &. But then later it arrives in GlyphCache.getCachedGlyph which uses >> and %, both of which give negative results here.
I wonder if this would fix the problem:

int segIndex = glyphCode >>> SEGSHIFT;
int subIndex = glyphCode & (SEGSIZE - 1);

@aditsu
Copy link

aditsu commented May 3, 2019

I was curious about that high slot number and looked into it some more. It appears that each logical font has a number of linked fonts which are used to resolve missing glyphs (and a slot is assigned for each linked font as well as the original font). In my case, the font is System, physical font LiberationSans-Regular, and it has a truckload of linked fonts (well, 147), about 90% of which are various versions of Noto Sans. Almost none of those linked fonts has that pencil glyph, and it goes all the way to slot 144 which seems to be the Symbola font.
I recently updated the Noto fonts (including CJK) on my system, and I noticed that it installed a ridiculous number of font files. I guess that pushed the number of slots over 128 (causing negative glyph codes). Now I wonder if the number of slots can ever reach or exceed 256...

@rcano
Copy link

rcano commented May 7, 2019

Any recent linux distro will trigger this bug for any unicode making javafx useless on linux... this is the kind of thing that should warrant a hotfix point release.

@aditsu
Copy link

aditsu commented May 7, 2019

An update: I've disabled a metric ***ton of Noto fonts using KDE's font manager (seriously, it said 1178 fonts, and that's excluding all the Noto fonts I think I might ever use), and now GlyphCache is not crashing anymore. This confirms my previous diagnosis.

@randomname8
Copy link

This bug has been opened for 8 months, seemingly no activity. Javafx is, as of now, unusable on any recent linux distribution.

@lion7
Copy link

lion7 commented Aug 31, 2019

I'm having exactly the same issue. I'm running on Arch Linux where the Noto Sans Regular font is configured as the system font (javafx calls it System Regular I believe). In this case I'm running a JDK14 build (version 14-jpackage+1-35 to be precise) and openjfx-13-ea+11.

In my application I'm using the character '👁' (\uD83D\uDC41). After debugging for a while I figured that this character results in the negative glyph code -2147482707, causing the same AIOOBE.

The negative value is caused by the bit shift in https://github.com/javafxports/openjdk-jfx/blob/develop/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CompositeGlyphMapper.java#L90.

See the screenshot below for the values before this method was called during my debugging.
After the compositeGlyphCode method is called the glyphCode becomes -2147482707.
Also note that the value of slot is 128, which is bitshifted in the compositeGlyphCode method:
128 << 24 = -2147483648.

Unfortunately I don't really know how to solve this problem. Skipping the call to compositeGlyphCode results in a different symbol. Maybe store the resulting value as a long?

Screenshot from 2019-08-31 13-42-49

@prrace
Copy link

prrace commented Sep 3, 2019

127 fonts should be enough for anyone :-)
We can (should) add similar logic into FX to limit the number of slots as I think we have in Java 2D code in Java SE.
If after looking at the first 127 fonts the system has configured as the "best" you are still looking for a code point you need then I think it is time to give up or suggest that the system needs reconfiguring.

@aditsu
Copy link

aditsu commented Sep 3, 2019

lion7 wrote:

Unfortunately I don't really know how to solve this problem.

I already suggested a solution (see my first comment). It is still not perfect - it will just push the limit to 255.

@lion7
Copy link

lion7 commented Sep 3, 2019

@aditsu you are correct, I just noticed you did exactly the same digging 🤦‍♂️
I'll try your proposed fix and see if my glyph renders correctly.

@KevinMX
Copy link

KevinMX commented Oct 7, 2019

@aditsu Solved my issue on Arch Linux, I was about to run HMCL under KDE and some guys seems to have the same issue (see https://github.com/huanghongxun/HMCL/issues/536)
Now the window is rendering correctly.

@1-alex98
Copy link

Have the same issue

@kevinrushforth
Copy link
Collaborator

This GitHub issue tracker is not actively tracked or managed. Please file a bug at bugreport.java.com. However, without a reproducible test case, we are not likely to be able to make progress on this issue.

If you are interested in contributing a fix for this issue, please see CONTRIBUTING.md in the official openjdk/jfx GutHub repo.

@timmc
Copy link

timmc commented Nov 17, 2019

@kevinrushforth There's already a reproducible test case earlier in the thread. (Worked for me on Debian 10 Linux, OpenJDK 11.) But, I hear you that this issue tracker is not monitored.

Interestingly, it's not just freezes; I also get graphics corruption. Here's what happens when I paste the "💥" emoji into a text field—a copy of the whole scene is flipped vertically and then inserted into a scrollpane:

image

@timmc
Copy link

timmc commented Nov 17, 2019

Here's a repro case with complete build config and everything, as a repository, if anyone gets around to filing a bug before me: https://gitlab.com/timmc/sscce-javafx-emoji-crash

@timmc
Copy link

timmc commented Nov 17, 2019

Filed a bug, with internal review ID 9062849.

@timmc
Copy link

timmc commented Nov 17, 2019

More info on workaround and diagnosis, following the Noto fonts lead. I found I have the following font packages installed in Debian with noto in the name:

  • fonts-noto-color-emoji
  • fonts-noto-core
  • fonts-noto-mono
  • fonts-noto-ui-core

Uninstalling just fonts-noto-core was sufficient to prevent the issue.

Is there further debugging I can do? For example, is there a way to prevent certain system fonts from being loaded by JavaFX, so that I can do a binary search and find if there are specific fonts that are causing the issue?

@aditsu
Copy link

aditsu commented Nov 18, 2019

@timmc

is there a way to prevent certain system fonts from being loaded by JavaFX, so that I can do a binary search and find if there are specific fonts that are causing the issue?

The issue is not really caused by specific fonts, it is caused by the number of fonts linked to the font you are using and missing the required glyph.

The reproducibility of the test case is contingent on the number and configuration of the fonts installed in the system.

@timmc
Copy link

timmc commented Nov 18, 2019

Ouch, got it. Is there a shippable workaround, like shipping with a set of fonts and somehow restricting the UI to only consider those fonts?

@aditsu
Copy link

aditsu commented Nov 19, 2019

That should be possible, by using loadFont and explicitly referencing those fonts in the application. I'm not sure if there's a mechanism for defining fallback fonts, or for configuring the fonts used by an application without modifying its code.

@timmc
Copy link

timmc commented Nov 19, 2019

I tried setting the font for a TextField by name (which worked) and then pasted in an emoji, and the app crashed. I think it's still looking at fallback fonts from the system.

@prrace
Copy link

prrace commented Dec 5, 2019

Please stop looking or updating at bugs on github. OpenJFX doesn't use them.
This report is being actively ignored.
You need to look here : https://bugs.openjdk.java.net/browse/JDK-8189092

@timmc
Copy link

timmc commented Dec 5, 2019

@prrace I'm aware of it, but the fact is that I can talk about debugging it and finding workaround with people here, and I don't see a way to get a login there. 🤷‍♂️

@1-alex98
Copy link

Same here this java bug tracker thing is awful. I can not comment there or whatsoever...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests