GithubHelp home page GithubHelp logo

debug's Introduction

Build Status

What

Java Agent for debugging LWJGL3 programs to prevent JVM crashes and resolve OpenGL errors.

Why

Because some errors in user programs can cause the JVM to crash without a meaningful error message, since LWJGL 3 is tuned for extreme speed at the expense of robustness.

How

  1. Download the lwjglx-debug-1.0.0.jar file from https://www.lwjgl.org/browse/addons/lwjglx-debug or build this Maven project via the instructions in the 'Build' section below
  2. Copy the lwjglx-debug-1.0.0.jar to any directory (henceforth called <cwd>)
  3. Start your LWJGL3 application with the JVM/VM argument (not program argument) -javaagent:<cwd>/lwjglx-debug-1.0.0.jar
    1. when using the command line, it should look like: java -javaagent:<cwd>/lwjglx-debug-1.0.0.jar -cp all/the/jars your.main.Class
    2. when using Eclipse, right-click your class with the main() method, goto 'Run As > Run Configurations...' and on the 'Arguments' tab inside the 'VM Arguments:' field enter -javaagent:<cwd>/lwjglx-debug-1.0.0.jar

Configuration

The following configuration properties are available to configure the library:

  • validate - Perform argument validation and check for GL errors on each GL call (enabled by default, set via system property -Dorg.lwjglx.VALIDATE or via Agent argument v)
  • trace - Generate a trace log (set via system property -Dorg.lwjglx.TRACE or via Agent argument t)
  • exclude - Exclude trace outputs for called methods matching a given GLOB pattern (set via Agent argument e)
  • nothrow - Do not throw a Java exception on any detected error but only log the error. Note that this may result in a JVM crash due to illegal arguments or GL errors. (set via system property -Dorg.lwjglx.NO_THROW or via Agent argument n)
  • debug - Log additional information about classfile transformations (this can be used to debug the library itself). (set via system property org.lwjglx.DEBUG or via Agent argument d)
  • output - Write LWJGL3 and LWJGLX debug and trace logging messages to a file (when this option is set, no output of LWJGL3 and LWJGLX is printed to stdout or stderr, but instead to the specified file). The file name is the value of this property. When the file name ends with .zip or .gz then a corresponding compressed archive file will be created to save storage space. In this case, the JVM must exit normally for the archive file to be finalized properly. (set via system property -Dorg.lwjglx.OUTPUT or via Agent argument o)
  • sleep - Thread.sleep() before calling each intercepted method (useful when following a call trace). The number of milliseconds are specified as the value of this property. (set via system property -Dorg.lwjglx.SLEEP or via Agent argument s)

Examples:

  • java -javaagent:lwjglx-debug-1.0.0.jar=t ... (generate a trace on stderr)
  • java -javaagent:lwjglx-debug-1.0.0.jar=t;o=trace.log (generate a trace written to file trace.log)
  • java -javaagent:lwjglx-debug-1.0.0.jar=t;o=trace.log.zip (generate a zip archive containing a single trace.log file)
  • java -javaagent:lwjglx-debug-1.0.0.jar=tn;o=trace.log (generate a trace written to file trace.log and do not throw on GL errors)
  • java -javaagent:lwjglx-debug-1.0.0.jar=t;e=*GL20*,*GL11.glVertex3f (generate a trace on stderr and exclude all methods from any class having GL20 in its name, as well as exclude glVertex3f from any class ending with GL11)

Build

  1. ./mvnw package
  2. see target/lwjglx-debug-1.0.0.jar

debug's People

Contributors

httpdigest avatar martinmisiak avatar spasi avatar swinxy avatar tsmock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

debug's Issues

[Request] Runtime disabling/enabling of inspections

I have a lot of code that flips or calls glBufferData an empty buffer (e.g. when there is no input to a compute shader this frame), and if this happens in a certain part of the code I'm pretty sure it's not a problem. It would be nice if I could tell the tool to suppress that warning while that code is executing.

Add simple profiling

Simple per-frame measures:

  • time (ms.)
  • number of drawn primitives (counted from all possible glDraw* calls)
  • number of OpenGL calls

That should be it for the beginning.

As for how to actually display the information:

  • an on-screen overlay is probably a good option, but it needs to have different rendering paths for different context capabilities/versions. Another issue is with hidden/offscreen rendering, where there is no window to display such information.
  • another option is the good old stdout/stderr printing. This is two drawbacks, though: First, the printed information will scroll very quickly and is therefore not amenable to being interpreted statistically. Second, printing to the console significantly slows down the application.
  • yet another option is to provide a web frontend and include a small servlet container such as an embedded Jetty in the Java Agent. The statistics will be collected by the instrumented application and reported to a WebSocket endpoint which the frontend is connected to. As for displaying the information, we could probably begin by using a simple JavaScript charting library, such as Chart.js.

The goal here is to establish a simple way to collect and display profiling data. Later, more profiling capabilities can be added, such as measuring the GPU render time (via timer query objects) of Java methods containing draw calls or other measured GL calls and display it in some sort of call trace, as is done by all other Java profiler tools (VisualVM, YourKit, JProfiler, ...).

Count number of vertices via query objects

Counting the number of effectively drawn vertices is hard when it comes to:

  • display lists
  • geometry shaders
  • tessellation shaders

For this, we should really use OpenGL Query Objects with the GL_PRIMITIVES_GENERATED target if supported by the context. The documentation says that it counts the actual "vertices" (not the primitives!), so is exactly what we want.
The only real problems are:

  • query objects are asynchronous (we might just wait on them at the end of the frame on glfwSwapBuffers to solve that)
  • the biggest problem however is that a user could also use an own query object with the same query target and query objects on the same target cannot be nested. One possible solution would be:
    • to first issue a single query trying to span all draw calls of a single frame
    • once we encounter a nested user query inside it we need to end our query and remember that we also would like to retrieve the user query's result at the end of the frame.
    • once the user query has ended via glEndQuery we start a new query (while still remembering that we also need to get the user query's result at the end of the frame)
    • at the end of the frame (at glfwSwapBuffers()) we wait on all issued queries (including user queries) and accumulate their results to the final number of vertices to report

Add "main thread" validation

Certain methods (like the window-related GLFW methods) may only be called in the main thread. We currently have no validation for this.
Since the Java Agent's premain method is started very early in the VM startup process in the main thread, we certainly know which thread is the main thread.

Profile GPU time for draw calls via query objects

Currently, we only count the CPU/host time it takes between two consecutive glfwSwapBuffers calls.
More interesting for bottleneck analysis however would be to know the actual time it takes the GPU to perform a draw call.

So, for contexts that support it, we could use OpenGL Query Objects with glQueryCounter and the GL_TIMESTAMP target to count the GPU time.

Correctly Handle GLX Calls

The JAWT demos use GLX in order to render GL content on Linux. Currently the debug jar has a fatal exception on o.l.o.GL.createCapabilities because it doesn't see that there is a current context.

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: No OpenGL context has been made current through recognized API methods (glfwMakeContextCurrent).

glPopClientAttrib() index bug?

The first argument to glGetVertexAttrib() is always zero. It should be 'i' I think.

        for (int i = 0; i < context.GL_MAX_VERTEX_ATTRIBS; i++) {
            /* Read enable state and buffer bindings */
            if (context.caps.OpenGL20) {
                context.currentVao.enabledVertexArrays[i] = org.lwjgl.opengl.GL20.glGetVertexAttribi(0, org.lwjgl.opengl.GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED) == 1;
                context.currentVao.initializedVertexArrays[i] = org.lwjgl.opengl.GL20.glGetVertexAttribi(0, org.lwjgl.opengl.GL15.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) != 0;
            } else if (context.caps.GL_ARB_vertex_shader) {
                context.currentVao.enabledVertexArrays[i] = org.lwjgl.opengl.ARBVertexShader.glGetVertexAttribiARB(0, org.lwjgl.opengl.ARBVertexShader.GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB) == 1;
                context.currentVao.initializedVertexArrays[i] = org.lwjgl.opengl.GL20.glGetVertexAttribi(0, org.lwjgl.opengl.ARBVertexBufferObject.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB) != 0;
            }
        }

Program stops "randomly" when trace parameter is active

Hello,

I am developing a small game engine on my free time, I decided to activate your agent with the "trace" parameter but when I do it the program stops after a while without even arriving at launch from the engine loop it stops at a random GLFW function and when I remove it it stops at the one before etc.

Without this parameter everything works flawlessly without memory leaks, freezes, lags, crashes, errors, etc.
Shouldn't this parameter make it possible to obtain a lot of information throughout the program, from the initialization, to the stop, passing through the loop?

Did you have an idea?

I am at your disposal to provide all the necessary information.

Good day !

Add source file and line number output to traced GL calls

The GL call trace outputs are good to see the general order of GL calls with their arguments and return values.
However, it is not easy to match the GL calls to the user source code they appear in. For this it would be great to annotate each GL call with the source file name and the line number in the IDE-recognized format "(filename:line)". This allows to click them in the IDE's console to jump to the respective line in the source code.

Currently, a full stacktrace is being generated for GL debug message callbacks using Throwable.getStackTrace(). A full stacktrace is likely not needed for each traced GL call, but only the last stracktrace element. For this, we do not even need to call into the JVM runtime, since we have the debug information already read from the classfile.

We just need to introduce two additional parameters (String sourcefile, int linenumber) in the call interface of the generated trace class, which are being fed by the Transformer class when GL calls are seen.

Possible desired output format:

[trace][1] (MyLwjglProgram.java:15)     glUseProgram(6)
[trace][1] (MyLwjglProgram.java:20)     glBindBuffer(GL_ARRAY_BUFFER, 3)
[trace][1] (MyLwjglProgram.java:123)    glVertexPointer(3, GL_FLOAT, 0, 0L)
[trace][1] (MyLwjglProgram.java:126)    glEnableClientState(GL_NORMAL_ARRAY)
[trace][1] (MyLwjglProgram.java:131)    glBindBuffer(GL_ARRAY_BUFFER, 4)
[trace][1] (MyLwjglProgram.java:133)    glNormalPointer(GL_FLOAT, 0, 0L)
[trace][1] (MyLwjglProgram.java:134)    glBindBuffer(GL_ARRAY_BUFFER, 0)

Of course, the output should be properly formatted with padding to account for different sourcefile and line number lengths.

Add CPU and GPU time profiling for code sections

Currently, the GPU (draw calls) and CPU time for the whole frame is recorded and plotted. For more fine-grained profiling it is of course desirable to be able to profile designated code sections separately.

There are the following options to designate those code sections:

  • just use the Java call stack and profile each method which contains at least one GL method call
  • let the user insert the start of a new code section using glStringMarkerGREMEDY
  • let the user indicate a (hierarchical) code section by glPushDebugGroup/glPopDebugGroup, which seems to be designed for exactly this use case

Even when OpenGL 4.3 or KHR_debug is not exposed by the GL driver, we can intercept the GLCapabilities field query and calls to those methods so that they do work when being run under the profiler.

The result should be a tree of code sections with their names, the number of encountered invocations/executions and the average GPU and CPU time spent.

[Question] Java 8 Compatibility

Hi, good afternoon. I'm very interested in this project, can I ask you two questions which troubled me for a while ?

  1. Is that possible to debug this project itself by setting breakpoints? I searched Chinese dev community and stackoverflow.com, but haven't find a good way to do this.
  2. I ran 'mvnw package' with JDK8, and errors showed as below. sorry for the localized output message, it's basically says the method buf.slice(index, length) expected none parameters but found two. I checked the issue#25 and commit history, but I still confused, it seems not support versions before JDK13 anymore.
D:\github\debug>mvnw package
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.lwjglx:lwjglx-debug >-----------------------
[INFO] Building LWJGLX/debug 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from oss.sonatype.org: https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl/3.2.4-SNAPSHOT/maven-metadata.xml
Downloading from repository.ow2.org: https://repository.ow2.org/nexus/content/repositories/snapshots/org/lwjgl/lwjgl/3.2.4-SNAPSHOT/maven-metadata.xml
Downloaded from oss.sonatype.org: https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl/3.2.4-SNAPSHOT/maven-metadata.xml (2.6 kB at 595 B/s)
Downloading from repository.ow2.org: https://repository.ow2.org/nexus/content/repositories/snapshots/org/lwjgl/lwjgl-opengl/3.2.4-SNAPSHOT/maven-metadata.xml
Downloading from oss.sonatype.org: https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl-opengl/3.2.4-SNAPSHOT/maven-metadata.xml
Downloaded from oss.sonatype.org: https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl-opengl/3.2.4-SNAPSHOT/maven-metadata.xml (2.6 kB at 4.4 kB/s)
Downloading from oss.sonatype.org: https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl-glfw/3.2.4-SNAPSHOT/maven-metadata.xml
Downloading from repository.ow2.org: https://repository.ow2.org/nexus/content/repositories/snapshots/org/lwjgl/lwjgl-glfw/3.2.4-SNAPSHOT/maven-metadata.xml
Downloaded from oss.sonatype.org: https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl-glfw/3.2.4-SNAPSHOT/maven-metadata.xml (2.6 kB at 14 B/s)
[INFO]
[INFO] --- maven-antrun-plugin:1.8:run (default) @ lwjglx-debug ---
[INFO] Executing tasks

main:
[INFO] Executed tasks
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ lwjglx-debug ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ lwjglx-debug ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 50 source files to D:\github\debug\target\classes
[INFO] /D:/github/debug/src/org/lwjglx/debug/Profiling.java: D:\github\debug\src\org\lwjglx\debug\Profiling.java使用或覆盖了已过时的 API。
[INFO] /D:/github/debug/src/org/lwjglx/debug/Profiling.java: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
[INFO] /D:/github/debug/src/org/lwjglx/debug/WeakIdentityHashMap.java: D:\github\debug\src\org\lwjglx\debug\WeakIdentityHashMap.java使用了未经检查或不安全的操作。
[INFO] /D:/github/debug/src/org/lwjglx/debug/WeakIdentityHashMap.java: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[182,32] 无法将类 java.nio.ByteBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[201,32] 无法将类 java.nio.CharBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[218,33] 无法将类 java.nio.ShortBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[235,31] 无法将类 java.nio.IntBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[252,32] 无法将类 java.nio.LongBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[269,33] 无法将类 java.nio.FloatBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[286,34] 无法将类 java.nio.DoubleBuffer中的方法 slice应用到给定类型;
  需要: 没有参数
  找到: int,int
  原因: 实际参数列表和形式参数列表长度不同
[INFO] 7 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  03:12 min
[INFO] Finished at: 2020-11-04T21:43:39+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project lwjglx-debug: Compilation failure: Compilation failure:
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[182,32] 无法将类 java.nio.ByteBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[201,32] 无法将类 java.nio.CharBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[218,33] 无法将类 java.nio.ShortBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[235,31] 无法将类 java.nio.IntBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[252,32] 无法将类 java.nio.LongBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[269,33] 无法将类 java.nio.FloatBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] /D:/github/debug/src/org/lwjglx/debug/RT.java:[286,34] 无法将类 java.nio.DoubleBuffer中的方法 slice应用到给定类型;
[ERROR]   需要: 没有参数
[ERROR]   找到: int,int
[ERROR]   原因: 实际参数列表和形式参数列表长度不同
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Add option to not throw on GL error

Currently, OpenGL errors raised by an OpenGL debug callback will be thrown as exception back to user code and can lead to process abort. This can be undesirable in cases where a user might want to react to OpenGL errors at a later point in time or get a log of all OpenGL errors in the application before fixing them.

We should provide an option to just report errors and not throw in such situations.

memRealloc on a filled-buffer throws Exception due to "no remaining elements"

ByteBuffer buf = memAlloc(8);
int bytes = 0;
for (int i = 0; i < 64; ++i) {
	buf.put((byte) i);
	++bytes;
	if (i + 1 == bytes)
		buf = memRealloc(buf, bytes * 2);
}
for (int i = 0; i < 64; ++i) 
	System.out.println(buf.get(i));
memFree(buf);

The code above throws an IllegalArgumentException in the memRealloc call.

Exception in thread "main" java.lang.IllegalArgumentException: buffer has no remaining elements. Did you forget to flip()/rewind() it?

Without the agent attached it works fine and to confirm I wrote the same code in C and had no issues.

LWJGL 3.2.1 and JDK 11

Handle GLbitmask/GLbitfield correctly

Here is what I think should be the correct way of handling those. The steps are being excercised for the example of "glBufferStorage" and its flags GLbitfield parameter:

  1. for all /registry/enums elements that have a type="bitmask" attribute, the generator has to build a separate group with the enum values defined in that element (hint: the "group" attribute cannot be used for anything since it is hardly ever referenced anywhere)
  2. for each /registry/feature/require (example GL_VERSION_4_4) and /registry/extensions/extension/require (example GL_ARB_buffer_storage) elements, we first have to search whether there is a <command> defined in it (example glBufferStorage) that takes at least one GLbitfield parameter. This information is found in the corresponding /registry/commands/command element.
  3. If we found at least one such command, we have to match all enum elements in /registry/feature/require (example GL_VERSION_4_4) and /registry/extensions/extension/require (example GL_ARB_buffer_storage) with all previously created bitmask groups to see which of the enums are bitfield enums. For each enum found in a group A that group A is then considered a candidate group when looking up the name(s) of a GLbitfield argument by its value for a called command defined by this extension or core GL version.

Issues when running on working code

When running with the profiler I got it to throw exceptions that does not happen under normal circumstances.

Log without agent.txt
Log with agent.txt

I've attached logs with and without the agent. It seems to mess with the state in unintended ways because these errors are from my own calls to glGetError. Also, I'm using multi-threaded shared-context to smooth texture loading but only some errors appear to be caused by that.

Java 9 Compatibility

When attempting to use this library on Java 9 it throws an exception because it can not access "ClassLoader.defineClass".

java.lang.AssertionError: Could not find method: ClassLoader.defineClass
	at [email protected]/org.lwjglx.debug.ClassUtils.<clinit>(ClassUtils.java:39)
	at [email protected]/org.lwjglx.debug.InterceptClassGenerator.generate(InterceptClassGenerator.java:348)
	at [email protected]/org.lwjglx.debug.Agent.transform_(Agent.java:182)
	at [email protected]/org.lwjglx.debug.Agent.transform(Agent.java:70)
	at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
	at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:550)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1007)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1086)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:760)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:681)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:606)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
	at net.gudenau.ScriptKiddie/net.gudenau.scriptkiddie.start.Start.main(Start.java:7)
java.lang.NoClassDefFoundError: Could not initialize class org.lwjglx.debug.ClassUtils
	at [email protected]/org.lwjglx.debug.InterceptClassGenerator.generate(InterceptClassGenerator.java:348)
	at [email protected]/org.lwjglx.debug.Agent.transform_(Agent.java:182)
	at [email protected]/org.lwjglx.debug.Agent.transform(Agent.java:70)
	at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
	at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:550)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1007)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1086)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:760)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:681)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:606)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
	[my stuff]

LWJGL 3.2.0 12: UnsupportedOperationException/NullPointerException

When using LWJGL 3.2.0 build 12 on OpenJDK 11 with the debug library it throws several java.lang.UnsupportedOperationException during class transformations and a java.lang.NullPointerException inside org.lwjgl.opengl.GL.createCapabilities.

Neither of these exceptions are thrown while LWJGLX are used as an agent.

java --version

openjdk 11 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

Java output:

/usr/lib/jvm/jdk-11/bin/java -javaagent:lwjglDebug/lwjglx-debug-1.0.0.jar -javaagent:/home/gudenau/.local/share/JetBrains/Toolbox/apps/IDEA-U/ch-0/182.4892.20/lib/idea_rt.jar=43771:/home/gudenau/.local/share/JetBrains/Toolbox/apps/IDEA-U/ch-0/182.4892.20/bin -Dfile.encoding=UTF-8 -p /home/gudenau/Desktop/projects/java/-snip-/Client/target/classes:/home/gudenau/.m2/repository/com/google/code/gson/gson/2.8.5/gson-2.8.5.jar:/home/gudenau/Desktop/projects/java/-snip-/IPC/target/classes:/home/gudenau/Desktop/projects/java/-snip-/Protocol/target/classes:/home/gudenau/.m2/repository/org/lwjgl/lwjgl/3.2.0/lwjgl-3.2.0.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl-glfw/3.2.0/lwjgl-glfw-3.2.0.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl-opengl/3.2.0/lwjgl-opengl-3.2.0.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl-stb/3.2.0/lwjgl-stb-3.2.0.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl/3.2.0/lwjgl-3.2.0-natives-linux.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl-glfw/3.2.0/lwjgl-glfw-3.2.0-natives-linux.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl-opengl/3.2.0/lwjgl-opengl-3.2.0-natives-linux.jar:/home/gudenau/.m2/repository/org/lwjgl/lwjgl-stb/3.2.0/lwjgl-stb-3.2.0-natives-linux.jar -m net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client
[LWJGL] Version: 3.2.0 build 12
[LWJGL] 	 OS: Linux v4.18.16
[LWJGL] 	JRE: 11 amd64
[LWJGL] 	JVM: OpenJDK 64-Bit Server VM v11+28 by Oracle Corporation
[LWJGL] Loading library (system): lwjgl
[LWJGL] 	Using SharedLibraryLoader...
[LWJGL] 	Found at: /tmp/lwjglgudenau/3.2.0-build-12/liblwjgl.so
[LWJGL] 	Loaded from org.lwjgl.librarypath: /tmp/lwjglgudenau/3.2.0-build-12/liblwjgl.so
[LWJGL] MemoryUtil accessor: MemoryAccessorUnsafe
[LWJGL] Warning: Failed to instantiate memory allocator: org.lwjgl.system.jemalloc.JEmallocAllocator. Using the system default.
[LWJGL] MemoryUtil allocator: DebugAllocator
[LWJGL] Loading library: glfw
[LWJGL] 	Using SharedLibraryLoader...
[LWJGL] 	Found at: /tmp/lwjglgudenau/3.2.0-build-12/libglfw.so
[LWJGL] 	Loaded from org.lwjgl.librarypath: /tmp/lwjglgudenau/3.2.0-build-12/libglfw.so
java.lang.UnsupportedOperationException
	at org.lwjglx.debug.org.objectweb.asm.ClassVisitor.visitNestMemberExperimental(ClassVisitor.java:248)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.accept(ClassReader.java:651)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.accept(ClassReader.java:391)
	at org.lwjglx.debug.Agent.transform_(Agent.java:205)
	at org.lwjglx.debug.Agent.transform(Agent.java:71)
	at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
	at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1095)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:760)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:681)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:606)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.ui.key.KeyLayoutManager.loadLayout(KeyLayoutManager.java:81)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.ui.key.KeyLayoutManager.<clinit>(KeyLayoutManager.java:20)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.start(Client.java:35)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.lambda$main$0(Client.java:25)
	at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.UnsupportedOperationException
	at org.lwjglx.debug.org.objectweb.asm.ClassVisitor.visitNestHostExperimental(ClassVisitor.java:158)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.accept(ClassReader.java:541)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.accept(ClassReader.java:391)
	at org.lwjglx.debug.Agent.transform_(Agent.java:205)
	at org.lwjglx.debug.Agent.transform(Agent.java:71)
	at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
	at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1095)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:760)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:681)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:606)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.ui.key.KeyLayoutManager.loadLayout(KeyLayoutManager.java:83)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.ui.key.KeyLayoutManager.<clinit>(KeyLayoutManager.java:20)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.start(Client.java:35)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.lambda$main$0(Client.java:25)
	at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.UnsupportedOperationException
	at org.lwjglx.debug.org.objectweb.asm.ClassVisitor.visitNestMemberExperimental(ClassVisitor.java:248)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.accept(ClassReader.java:651)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.accept(ClassReader.java:391)
	at org.lwjglx.debug.Agent.transform_(Agent.java:205)
	at org.lwjglx.debug.Agent.transform(Agent.java:71)
	at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:246)
	at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1095)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:760)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:681)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:606)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.start(Client.java:37)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.lambda$main$0(Client.java:25)
	at java.base/java.lang.Thread.run(Thread.java:834)
[LWJGL] Loading library (system): lwjgl_opengl
[LWJGL] 	Using SharedLibraryLoader...
[LWJGL] 	Found at: /tmp/lwjglgudenau/3.2.0-build-12/liblwjgl_opengl.so
[LWJGL] 	Loaded from org.lwjgl.librarypath: /tmp/lwjglgudenau/3.2.0-build-12/liblwjgl_opengl.so
[LWJGL] Loading library: libGL.so.1
[LWJGL] 	libGL.so.1 not found in org.lwjgl.librarypath=/tmp/lwjglgudenau/3.2.0-build-12
[LWJGL] 	Loaded from system paths: /usr/lib/x86_64-linux-gnu/libGL.so.1
[LWJGL] Java 9 optimizations enabled
[LWJGL] [GL] Using OpenGL 4.3 for error logging.
[LWJGL] [GL] Warning: A non-debug context may not produce any debug output.
Exception in thread "New Main" java.lang.NullPointerException
	at org.lwjglx.debug.opengl.GL.createCapabilities(GL.java:39)
	at org.lwjglx.debug.$Proxy$5.createCapabilities1(Unknown Source)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.start(Client.java:40)
	at net.gudenau.-snip-.Client/net.gudenau.-snip-.client.Client.lambda$main$0(Client.java:25)
	at java.base/java.lang.Thread.run(Thread.java:834)

Output extension GLenum name in trace when extension function called

Currently, all GLenum values are resolved to their core name, when available. This even applies in situations when people call ARB/EXT/NV/... extension functions and those functions define alias names for the same core GLenum.
In this case, we should rather output the GLenum name defined by the extension when that extension defines a name of that particular enum value.
All the metadata for this is already available in the gl.xml:

  • which extension defines which GLenums
  • which GL call belongs to which extension

Add color buffer readback and video encoding

What:

  • build FFmpeg with the minimal required muxers, encoders, protocols and filters: libx264 (provides best compression/speed ratio, i.e. libx265, although phenomenally better at compression rate, is not yet suited for realtime video capture because it is too slow)
  • add shared library loading mechanism to the Java Agent (like LWJGL3 does it) and include FFmpeg libraries in build
  • add configuration option to enable screen capturing (specify output file or folder)

Store GLmetadata enums in String[] array

Currently, all enums in all enum groups are simply stored in a HashMap, which is wasteful regarding space and runtime, since the enum values are rather densely distributed. Therefore, space requirements and lookup time can be improved by simply allocating a contiguous associative String[] array holding the names of all GLenum values in the effective interval min < max where min and max are the lower and upper bounds of assigned GLenum values.

On-demand loading of enum values into that array can still be used as is now, by lazily populating the respective needed array elements.

Exceptions when running the debug agent.

My project works but when I add the agent to the vm arguments in eclipse, it seems to change the main thread and I get the following stack trace. Is it possible that using this debug tool changes my main thread so that my glfwInit is now called in another thread? Is there a way to fix that in my code?

[LWJGL] Version: 3.2.2 build 10
[LWJGL] 	 OS: Windows 10 v10.0
[LWJGL] 	JRE: 11.0.2 amd64
[LWJGL] 	JVM: OpenJDK 64-Bit Server VM v11.0.2+9 by Oracle Corporation
[LWJGL] Loading library (system): lwjgl
[LWJGL] 	Using SharedLibraryLoader...
[LWJGL] 	Found at: C:\Users\ramho\AppData\Local\Temp\lwjglramho\3.2.2-build-10\lwjgl.dll
[LWJGL] 	Found at: C:\Users\ramho\AppData\Local\Temp\lwjglramho\3.2.2-build-10\lwjgl.dll
[LWJGL] 	Loaded from org.lwjgl.librarypath: C:\Users\ramho\AppData\Local\Temp\lwjglramho\3.2.2-build-10\lwjgl.dll
[LWJGL] Java 9 stack walker enabled
[LWJGL] Warning: Failed to instantiate memory allocator: org.lwjgl.system.jemalloc.JEmallocAllocator. Using the system default.
[LWJGL] MemoryUtil allocator: DebugAllocator
[LWJGL] Loading library: glfw
[LWJGL] 	Using SharedLibraryLoader...
[LWJGL] 	Found at: C:\Users\ramho\AppData\Local\Temp\lwjglramho\3.2.2-build-10\glfw.dll
[LWJGL] 	Loaded from org.lwjgl.librarypath: C:\Users\ramho\AppData\Local\Temp\lwjglramho\3.2.2-build-10\glfw.dll
[trace] (Window.java:57)                createPrint(java.io.PrintStream@d7fbb24) =  pointer [0x20E3F310000]
java.lang.IllegalStateException: Method glfwInit was called in thread [Thread[GAME_LOOP_THREAD,5,main]] which is not the main thread.
	at org.lwjglb.engine.Window.init(Window.java:60)
	at org.lwjglb.engine.GameEngine.init(GameEngine.java:62)
	at org.lwjglb.engine.GameEngine.run(GameEngine.java:52)
	at java.base/java.lang.Thread.run(Thread.java:834)
Exception in thread "GAME_LOOP_THREAD" java.lang.NullPointerException
	at org.lwjglb.game.DummyGame.cleanup(DummyGame.java:192)
	at org.lwjglb.engine.GameEngine.cleanup(GameEngine.java:96)
	at org.lwjglb.engine.GameEngine.run(GameEngine.java:57)
	at java.base/java.lang.Thread.run(Thread.java:834)
[LWJGL] 16 bytes leaked, thread 12 (GAME_LOOP_THREAD), address: 0x20E3F310000
	at org.lwjgl.system.Callback.create(Callback.java:133)
	at org.lwjgl.system.Callback.<init>(Callback.java:83)
	at org.lwjgl.glfw.GLFWErrorCallback.<init>(GLFWErrorCallback.java:60)
	at org.lwjgl.glfw.GLFWErrorCallback$1.<init>(GLFWErrorCallback.java:97)
	at org.lwjgl.glfw.GLFWErrorCallback.createPrint(GLFWErrorCallback.java:97)
	at org.lwjglx.debug.$Proxy$14.createPrint18(Unknown Source)
	at org.lwjglb.engine.Window.init(Window.java:57)
	at org.lwjglb.engine.GameEngine.init(GameEngine.java:62)
	at org.lwjglb.engine.GameEngine.run(GameEngine.java:52)
	at java.base/java.lang.Thread.run(Thread.java:834)

NoClassDefFoundError: org/lwjglx/debug/RT

I’m trying to troubleshoot a LWJGL application using lwjglx-debug.

When running the application, I get a java.lang.NoClassDefFoundError: org/lwjglx/debug/RT exception.
Command line I’m using to run the application: JAVA_HOME="$(/usr/libexec/java_home -v 1.8)" java -javaagent:"${HOME}/Downloads/lwjglx-debug-1.0.0.jar" -cp "${HOME}/workspace/josm/core/dist/josm-custom.jar:${HOME}/.ivy2/cache/org.lwjgl/lwjgl/jars/lwjgl-3.3.1.jar:${HOME}/Downloads/lwjglx-debug-1.0.0.jar" org.openstreetmap.josm.gui.MainApplication
I’ve also tried some variations (with and without the lwjglx-debug-1.0.0.jar in classpath, an uber jar with all the LWJGL jars packed into it, Java 8 and Java 11)

Source code locations:

  • Main application (JOSM): https://josm.openstreetmap.de/svn/trunk (partially mirrored at https://github.com/JOSM/josm )
    • No GL/Vulkan/Metal here (except from Java 2d in Java itself).
  • JOSM Plugin (kendzi3d): kendzi/kendzi3d#103
    • Note that this PR is moving kendzi3d from JOGL to LWJGL. kendzi3d uses immediate mode, and some parts of the PR are moving it to VBO/VAO pipelines. The PR has working code, but I can provide a diff that breaks it (and is what I am trying to debug)

System information:

  • System: MacBook Pro (15-inch, 2017)
  • OS: Mac OS X 12.3
  • Java: 8, 11, 17 (all are Eclipse Temurin distributions)
  • GPU: Radeon Pro 555 2GB, Intel ID Graphics 630 1536 MB

Simple bash script to reproduce (note: you will be swamped with exceptions, and this does not download the plugin files that I actually want to debug)

$ curl -LO https://josm.openstreetmap.de/josm-tested.jar
$ curl -LO https://build.lwjgl.org/addons/lwjglx-debug/lwjglx-debug-1.0.0.jar
$ curl -LO https://build.lwjgl.org/release/latest/bin/lwjgl/lwjgl.jar
$ java -javaagent:"$(pwd)/lwjglx-debug-1.0.0.jar" -cp "$(pwd)/lwjgl.jar:$(pwd)/josm-tested.jar" org.openstreetmap.josm.gui.MainApplication

Additional notes:
adding =t to the agent doesn’t make a difference
I have to use the workaround from #29 (I'm constrained to Swing for UI).
Everything works properly in a Fedora 35 Silverblue VM (with java-1.8.0-openjdk layered on top).

Stacktrace:

2022-03-31 13:42:30.787 SEVERE: Handled by bug report queue: java.lang.NoClassDefFoundError: org/lwjglx/debug/RT
java.lang.NoClassDefFoundError: org/lwjglx/debug/RT
	at apple.laf.JRSUIControl.loadBufferWithChanges(JRSUIControl.java:140)
	at apple.laf.JRSUIControl.paintImage(JRSUIControl.java:219)
	at apple.laf.JRSUIControl.paint(JRSUIControl.java:208)
	at com.apple.laf.AquaPainter$AquaSingleImagePainter.createImage(AquaPainter.java:200)
	at com.apple.laf.AquaPainter$AquaSingleImagePainter.lambda$paintFromSingleCachedImage$0(AquaPainter.java:178)
	at sun.awt.image.MultiResolutionCachedImage.getResolutionVariant(MultiResolutionCachedImage.java:66)
	at sun.awt.image.MultiResolutionCachedImage.getBaseImage(MultiResolutionCachedImage.java:106)
	at sun.awt.image.AbstractMultiResolutionImage.getWidth(AbstractMultiResolutionImage.java:82)
	at sun.awt.image.MultiResolutionCachedImage.getWidth(MultiResolutionCachedImage.java:89)
	at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3269)
	at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3221)
	at com.apple.laf.AquaPainter$AquaSingleImagePainter.paintFromSingleCachedImage(AquaPainter.java:186)
	at com.apple.laf.AquaPainter$AquaSingleImagePainter.paint(AquaPainter.java:141)
	at com.apple.laf.AquaPainter.paint(AquaPainter.java:90)
	at com.apple.laf.AquaProgressBarUI.paint(AquaProgressBarUI.java:187)
	at com.apple.laf.AquaProgressBarUI.paint(AquaProgressBarUI.java:168)
	at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
	at javax.swing.JComponent.paintComponent(JComponent.java:780)
	at javax.swing.JComponent.paint(JComponent.java:1056)
	at javax.swing.JComponent.paintChildren(JComponent.java:889)
	at javax.swing.JComponent.paint(JComponent.java:1065)
	at javax.swing.JComponent.paintChildren(JComponent.java:889)
	at javax.swing.JComponent.paint(JComponent.java:1065)
	at javax.swing.JComponent.paintChildren(JComponent.java:889)
	at javax.swing.JComponent.paint(JComponent.java:1065)
	at javax.swing.JComponent.paintChildren(JComponent.java:889)
	at javax.swing.JComponent.paint(JComponent.java:1065)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
	at javax.swing.JComponent.paintChildren(JComponent.java:889)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
	at javax.swing.JComponent.paint(JComponent.java:1042)
	at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
	at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
	at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
	at java.awt.Container.paint(Container.java:1978)
	at java.awt.Window.paint(Window.java:3906)
	at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
	at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
	at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
	at java.awt.event.InvocationEvent.dispatch$$$capture(InvocationEvent.java:311)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Add option to direct log and trace output to file

Currently, all logging and tracing output is written to stderr. This might not be optimal for the following reasons:

  • the user outputs logging information herself and those custom outputs can be hard to identify, especially when tracing
  • the latency of outputting to the console slows down the user application

The second situation can be solved today with using shell pipes to direct stderr to a file.
The first situation cannot be solved by this.

We have the following options to specify a file name:

  • as a Java Agent argument (currently not used for anything)
  • as a system property

org.lwjglx.debug.opengl.GL.createCapabilities(GL.java:59) fires java.lang.NullPointerException

Hi,

as titled, it crashes here:

    Context context = CURRENT_CONTEXT.get();
    context.caps = caps;

I double cheched and context is indeed null

In my app I do the following:

    glfwWindow = GlfwWindow.fromWin32Window(hwnd).apply {
        makeContextCurrent()
        println("current: $isCurrent")
        createCapabilities(forwardCompatible = false)
    }
  • create the glfw window
  • make context current
  • check if it's really current (glfwGetCurrentContext == window.handle)
  • and then create the capabilities with the desidered forwardCompatibility option

And the last step is exactly where debug crashes

What is wrong?

ps: glfw is already initialized at that point, I also have GLFWErrorCallback.createPrint().set() but I dont get any error from there

Generate trace classes per call site class

Currently, whenever a call site is found that invokes a GL/GLFW method, a trace class is being generated for the whole GL/GLFW class and all methods contained in it. This adds a significant amount to startup/classloading time when the Java Agent is asked by the JVM to execute for the loaded user class.

This gets even more troublesome when we assume user code to call into various different GLxx classes, such as GL11, GL12, GL15, GL20 and GL32 and only calling a handful of methods from each of those.

Therefore, we should change the trace class generation strategy to generate a trace class per user class and simply couple all GL methods from all used GLxx classes together. This in turn can mean that we might generate trace methods for the same GLxx class and method multiple times when they are being called from multiple client classes.

java.lang.NoSuchMethodError: org.lwjglx.debug.RT.returnValue(DLorg/lwjglx/debug/MethodCall;)D

I attempted to run Minecraft 1.13 snapshot with lwjglx debug (because on my system it has a strange memory leak and I'm trying to find the cause on my own). After adding nothrow and trace options, I got this exception:

Exception in thread "main" java.lang.NoSuchMethodError: org.lwjglx.debug.RT.returnValue(DLorg/lwjglx/debug/MethodCall;)D
	at org.lwjglx.debug.$Proxy$44.10(Unknown Source)
	at bjh.B(SourceFile:2117)
	at net.minecraft.client.main.Main.main(SourceFile:45)

Java 18 compatibility

I saw there was a pull request to update dependencies for Java 18 compatibility, but even building against 402539a using ./mvnw clean package, the resulting target/lwjglx-debug-1.0.0.jar does not seem to work with Java 18. It's exactly what you'd expect:

java.lang.IllegalArgumentException: Unsupported class file major version 62
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.<init>(ClassReader.java:196)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.<init>(ClassReader.java:177)
	at org.lwjglx.debug.org.objectweb.asm.ClassReader.<init>(ClassReader.java:163)
	at org.lwjglx.debug.Agent.transform_(Agent.java:140)
	at org.lwjglx.debug.Agent.transform(Agent.java:65)
[...]

Oddly enough, in the source I have, the new ClassReader occurs one line later, on line 141, but is reported as being on 140 for reasons I cannot fathom.

There was also one stage of the maven build where it threw an error (not counting the intentional errors in testing), and I'm not sure if it's significant or not:

[INFO] --- maven-antrun-plugin:3.1.0:run (default) @ lwjglx-debug ---
[INFO] Executing tasks
[ERROR]      [java] java.lang.UnsupportedOperationException: The Security Manager is deprecated and will be removed in a future release
     [java] 	at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:194)
     [java] 	at org.apache.tools.ant.taskdefs.Java.run(Java.java:891)
     [java] 	at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:231)
     [java] 	at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:135)

Method references aren't proxied properly.

Sample code, tested on OpenJDK 17:

Supplier<Integer> func = GL30C::glGenVertexArrays;
glBindVertexArray(func.get());
glDisableVertexAttribArray(0);

will crash with

java.lang.NullPointerException: Cannot read field "enabledVertexArrays" because "org.lwjglx.debug.org.lwjgl.opengl.Context.currentContext().currentVao" is null
    at org.lwjglx.debug.org.lwjgl.opengl.GL20.glDisableVertexAttribArray(GL20.java:47)
    at org.lwjglx.debug.$Proxy$1.glDisableVertexAttribArray3(Unknown Source)

...suggesting that method reference to glGenVertexArrays didn't go through a proxy object

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.