Tag Archives: JDK

[Solved] Using JDK dynamic agent to customize SPI Error: UndeclaredThrowableException

preface

In the last article, we talked about how to integrate custom SPI with sentinel to realize fuse current limiting. In the process of implementing integration testing, an interesting exception Java lang.reflect.Undeclaredtowableexception. At that time, a global exception was caught in the code layer. The example is as follows

@RestControllerAdvice
public class GlobalExceptionHandler {


    @ExceptionHandler(Exception.class)
    public AjaxResult handleException(Exception e) {
        String msg = e.getMessage();
        return AjaxResult.error(msg,500);
    }


    @ExceptionHandler(BlockException.class)
    public AjaxResult handleBlockException(BlockException e) {
        String msg = e.getMessage();
        return AjaxResult.error(msg,429);
    }

}

Originally, it was expected that blockexception would be captured when current limiting was triggered, and then a layer of rendering would be encapsulated. Unexpectedly, blockexception could not be captured alive and dead.

Troubleshooting

Through debugging, it is found that the problem is caused by the JDK dynamic agent. Later, I found some information. Later, I found a paragraph in the official API document

The main idea is that if the invoke method of the call handler of the proxy instance throws a checked exception (which cannot be assigned to runtimeException or throwable of error), and the exception cannot be assigned to any exception class declared by the throws sub Office of the method, the method call on the proxy instance throws an undeclaredtrowableexception.

In this passage, we can analyze the following scenarios

1. There is no declared exception on the real instance method, and the checked exception is thrown when the proxy instance is called

2. The real instance method declares a non checked exception, and the proxy instance throws a checked exception when calling

Solution

Method 1: the real instance also declares the detected exception

Example:

public class SqlServerDialect implements SqlDialect {
    @Override
    public String dialect() throws Exception{
        return "sqlserver";
    }

Method 2: JDK can capture the invoke of dynamic agent, and can customize the exception thrown at the same time

Example:

 @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        CircuitBreakerInvocation invocation = new CircuitBreakerInvocation(target,method,args);

        try {

            return new CircuitBreakerInvoker().proceed(invocation);
        } catch (Throwable e) {
            throw new CircuitBreakerException(429,"too many request");
        }

    }

Method 3: catch the invocationtargetexception exception and throw the real exception

The reason why we need invocationtargetexception is that our custom exception will be wrapped by invocationtargetexception

Example

  @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        CircuitBreakerInvocation invocation = new CircuitBreakerInvocation(target,method,args);

        try {

            return new CircuitBreakerInvoker().proceed(invocation);
            //Use InvocationTargetException is java.lang.reflect.UndeclaredThrowableException
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }

    }

summary

If it is a component implemented by ourselves, we recommend directly using scheme 3, that is, capturing invocationtargetexception exceptions.

If the component is implemented by a third party, the recommended scheme 1 is to declare an exception in the called instance method. For example, when using springcloud Alibaba sentinel, there is a probability that an undeclaredtowableexception exception will occur, because it is also based on a dynamic agent, and the blockexception thrown by it is also a checked exception. Examples are as follows

public class SqlServerDialect implements SqlDialect {
    @Override
    public String dialect() throws BlockException{
        return "sqlserver";
    }

If you use a third-party component instead of scheme 1, you can also add a layer of agent on the basis of the third-party component, or intercept the third-party component.

An error is reported after eclipse changes the JDK version

In the actual development process, we may need to change the JDK version due to the needs of the project. However, an error will be reported after replacement, as follows:

Java compiler level does not match the version of the installed Java project facet.

Solution:

Step 1: set the eclipse JDK version

Windows—-> Preferences—-> Java—-> Installed JREs

 

Step 2: set the JDK compiled version

Windows—-> Preferences—-> Java—-> Compiler

 

Step 3: right click the project and set the JDK version of the project to the above unified version

Right click the item – > Properties—-> Java Compiler

 

  Note: the above versions should be unified

 

[Solved] IDEA JDK is 1.8 Warning: Diamond types are not supported at this language level

help——about View the version of ide.

IntelliJ IDEA 2017.3.7 (Ultimate Edition)
Build #IU-173.4710.11, built on April 4, 2019
Licensed to Rover12421/Rover12421
You have a perpetual fallback license for this version
Subscription is active until December 31, 2099
JRE: 1.8.0_152-release-1024-b18 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 7 6.1

A newly created maven project, created by clicking next, resulted in the following error when newKafkaProducer<>.

Diamond types are not supported at this language level

You can see that Diamond is a feature of JDK1.7, so 1.5 is definitely not supported.

Right click on the project and select Open Module Setting

Open the following pop-up window, the error is that the default Language level here is still 5.0

Multiple JDK switch and solution of could not find java.dll exception in win10 environment

What are the eight life cycle hook functions of Vue>>>

Note: mainly switch between jdk1.7 and JDK1.8

1. Java needs to be modified every time JDK is switched_ HOME

2. Edit the path environment variable, as shown in the figure, and set% Java_ Home% bin and% Java_ Move home% \ bin to the top two columns

3. Add the Java application to the start toolbar java file and select the enabled JDK version

4. Modify the registry information of Java in the computer

Win + R pop up the running window, enter regedit, enter the interface “Registry Editor”, and then find

HKEY_ LOCAL_ Machine/software/javasoft/Java development kit/CurrentVersion

HKEY_ LOCAL_ Machine, software, javasoft, Java runtime environment, current version

5. Open the CMD window and input Java – version to detect

It’s not right to report an error

Error: Registry key ‘Software\JavaSoft\Java Runtime Environment’\CurrentVersion’
has value ‘1.7’, but ‘1.8’ is required.
Error: could not find java.dll
Error: Could not find Java SE Runtime Environment.

6. There are mainly the following situations when the error message appears

6.1 because a key in the registry has been localized to a Chinese name.
[HKEY]_ LOCAL_ Machine/software/javasoft/Java runtime environment]
changed to:
[HKEY_ LOCAL_ Then press F3 to change all the found “Java runtime environment” and “Java runtime environment”.  

6.2 delete the java.exe, javaw.exe and javaws.exe in the C: Windows/system32 file

7. Check again, OK

[Java] deepin solves the problem of picked up in JDK_JAVA_Options:-AWT. Usesystemaafontsettings=gasp

Domestic deepin Linux operating system, in accordance with the manual JDK, as long as a run Java related commands will appear such a sentence

Picked up _ JAVA_ OPTIONS: -Dawt.useSystemAAFontSettings=gasp

e.g.
java -version

Picked up _JAVA_OPTIONS:   -Dawt.useSystemAAFontSettings=gasp
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

In eclipse, MyEclipse and Android studio, when you run a program, there are also related statements, which make people angry. This problem has been bothering me for a long time

Today, we have finally found a solution:
for different operating systems, refer to the solution(Basically the same)

The main reasons are as follows

The original openjdk setting interferes with the manual installation of JDK. The interfering file is/etc/profile.d/java-awt-font-gasp.sh

The solution(1)

1、 Copy the relevant openjdk settings to JRE in your JDK
sudo CP – P/etc/java-7-openjdk/properties/opt/Java/jdk1.8.0_ 66/jre/lib/

If it’s just to solve the above problems, it can be avoided, but for the sake of insurance

2、 Back up files

sudo cp -p /etc/profile.d/java-awt-font-gasp.sh ~/.local/share/init.d-bak

3、 Delete file

sudo rm /etc/profile.d/java-awt-font-gasp.sh

4、 Log out or restart to solve the problem

Solutions(2)

Some time ago, I did the system again, but I still met the same problem, but I didn’t solve the problem according to the previous method. The new solutions are summarized

【1】 Find the/etc/profile file and add the following before the JDK environment variable:

unset _JAVA_OPTIONS

【2】 Log off the user and solve the problem

Principle:

I found that the main reason for this problem is that there is an environment variable named in the environment variable_ JAVA_ However, no matter how the terminal is deleted, the final result will only affect the current terminal. There are still problems when opening other terminals or software. But I didn’t find the data to add this in any environment variable file. I thought: can I disable this environment variable directly when the system is loading, so I added the above content to the/etc/profile file, and the problem was solved

The selected directory is not a valid home for JDK when IntelliJ idea is imported into JDK

  • The JDK version is not compatible with the IDEA version:

Too high JDK version may cause this problem. JDK compatible with IDEA is required.

For example, if IDEA2016.3.8 is used and jdk-10.0.1_windows-x64_bin is used for JDK, this problem will always occur. After re-downloading jdk-8u171-windows-x64.exe and installing it, the problem was solved successfully!

 

Determine whether JDK is 64 bit or 32-bit

Sun has a Java System property to determine the bitness of the JVM: 32 or 64:

sun.arch.data.model=32//32bitJVM
sun.arch.data.model=64//64bitJVM

You can use

System.getProperty("sun.arch.data.model")

to determine if its 32/64 from the program.

From thesun.docs:

When writing Java code, how do I distinguish between 32 and 64-bit operation?

There’s no public API that allows you to distinguish between 32 and 64-bit operation. Think of 64-bit as just another platform in the write once, run anywhere tradition. However, if you’d like to write code which is platform specific (shame on you), the system property sun.arch.data.model has the value “32”, “64”, or “unknown”.

The only good reason is if your java code is dependent upon native libraries and your code needs to determine which version (32 or 64bit) to load on startup.

How to Solve JAVA Error: “well-known file is not secure” ?

Recently, JDK tools jmap and jstack are often used to dump JVM heap and JVM thread stack log to analyze problems. When executing these two commands, I was most puzzled when I encountered this problem: well-known file is not secure

eg:

Google the Internet and find the answer on stackoverflow http://stackoverflow.com/questions/9100149/jstack-well-known-file-is-not-secure?rq=1

It means:

We can find/TMP/hsperfdata on the machine_ $user/$PID is such a file. When we execute jmap or jstack, we first check whether the user executing the command is in contact with hsperfdata_ The users of the $user file are consistent. If not, switch to consistent and then execute.

Get current heap snapshot

jmap – dump:format=b ,file=./ heap.hprof 20344(pid)
20344: well-known file is not secure

sudo -u app-cfg-api jmap – dump:format=b ,file=./ heap.hprof 20344
Dumping heap to /tmp/hsperfdata_ app-cfg-api/ heap.hprof …
Heap dump file created