Java 知多少

概念

全限定名 = 包名 + 类型

对象拷贝:在 Java 中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

CMS GC: 避免在老年代垃圾收集时出现长时间的卡顿,主要通过两种手段来达成: 1、不对老年代进行整理,而是使用空闲列表(free-lists)来管理内存空间的回收 2、在 mark-and-sweep (标记-清除) 阶段的大部分工作和应用线程一起并发执行。

happens-before, 指令重排

垃圾回收

class文件 JVM 只认识 .class 文件,它不关心是何种语言生成了 .class 文件,只要 .class 文件符合 JVM 的规范就能运行。 Class 文件是二进制文件,它的内容具有严格的规范,文件中没有任何空格,全都是连续的 0/1。Class 文件 中的所有内容被分为两种类型:无符号数、表。

静态代理、动态代理 Java中两种常见的动态代理方式:JDK原生动态代理和CGLIB动态代理。

注解 如果说注释是写给人看的,那么注解就是写给程序看的。它更像一个标签,贴在一个类、一个方法或者字段上。它的目的是为当前读取该注解的程序提供判断依据。比如程序只要读到加了@Test的方法,就知道该方法是待测试方法,又比如@Before注解,程序看到这个注解,就知道该方法要放在@Test方法之前执行。 所谓元注解,就是加在注解上的注解。

动态加载jar

动态加载class

pojo

语法

数据类型

String:适用于少量的字符串操作的情况 StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况 StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

HashTable HashMap ConcurrentHashMap

stream

synchronized ReentrantLock ReentrantReadWriteLock

JVM

你可以参考Java 虚拟机底层原理知识总结

内存空间

老年代问题:

类的生命周期

类的运行时绑定。类加载过程包括加载、验证、准备、解析、初始化。

JVM空间配置参数

jmap命令

项目构建

maven

gradle

ant

ivy

有用的maven插件

    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.1</version>
    <configuration>
    <forkMode>once</forkMode>
    <argLine>-Xmx102400m -Xms51200m -XX:MaxDirectMemorySize=1024m</argLine>
    </configuration>

强大的三方库

guava

Google开源的基础类库, 包含了对:集合,缓存,并发库,字符串处理, I/O等各个方面的支持

本地缓存,guava提供的cache是一个简洁、高效,易于维护的。

字符串处理

新集合类型

MyBatis

数据库(持久层)框架

Spring

Spring框架为开发Java应用程序提供了全面的基础架构支持。 Spring Boot基本上是Spring框架的扩展,它消除了设置Spring应用程序所需的XML配置,为更快,更高效的开发生态系统铺平了道路。

Spring Data JPA

Netty

netty比nio好在哪儿?

jni

c/c++

Native.synchronizedLibrary

JNA

https://github.com/java-native-access/jna 开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。

Java SPI META-INF/services

SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。

py4j

https://www.py4j.org/ https://www.cnblogs.com/xun-meng/p/12195854.html Py4J 使得 Python 程序可以利用 Python 解释器直接调用Java虚拟机中的 Java 对象,也可以让 Java 调用 Python 对象,有点像 Python 版的 JNI。 PySpark就是使用Py4J来进行Java和Python的互通。 Java和Python分别运行在独立的进程中,通过RPC调用。

下面是python代码访问java对象的例子。 在例子中Python借助GatewayServer来访问JVM。先启动java程序,后运行python程序。

import py4j.GatewayServer;
import java.util.Random;
public class EntryPoint {
    private static final Random random = new Random();
    public int randInt() { //这个是目标方法,我们让python调用它
        return random.nextInt();
    }
    public static void main(String[] args) {
        EntryPoint app = new EntryPoint();
        GatewayServer gatewayServer = new GatewayServer(app); // 实例化entry_point, 允许 Python 程序通过本地网络套接字与 JVM 通信
        gatewayServer.start();
        System.out.println("Gateway Server Started");
    }
}
from py4j.java_gateway import JavaGateway
gateway = JavaGateway()
if __name__ == '__main__':
    a = gateway.entry_point.randInt() # 从 Java-EntryPoint 入口点调用randInt函数
    print(a)

下面这个例子是java回调python实现的方法。 在例子中用python代码去implement出java的interface。先启动java程序,后运行python程序。本质上是python调用java,然后java由回调了python方法。

public interface FunInterface { // 这是java接口,我们希望用python实现它
    Object fun(Object source);
}
import py4j.GatewayServer;
public class EntryPoint {
    public String input = "xxx";
    public void callFun(FunInterface obj) { // 这个是目标方法,我们让python调用它,但其实现却又是python实现
        obj.fun(input)
    } 
    public static void main(String[] args) {
        EntryPoint app = new EntryPoint();
        GatewayServer gatewayServer = new GatewayServer(app); // 实例化entry_point,允许Python程序通过本地网络套接字与 JVM 通信
        gatewayServer.start();
        System.out.println("Gateway Server Started");
    }
}
class PythonListener(object):
    def __init__(self, gateway): # 构造函数传入JavaGateway
        self.gateway = gateway
    class Java:
        implements = ["Java接口全限定名.xx.xx.FunInterface"] # 实现一个java中定义的interface
    def fun(self, input):
        output = "this method is implemented by python"
        return output

if __name__ == "__main__":
    gateway = JavaGateway(callback_server_parameters=CallbackServerParameters())
    listener = PythonListener(gateway)
    gateway.entry_point.callFun(listener) # 从 Java-EntryPoint 入口点调用callFun函数

上面两个例子都是先启动java程序作为GateWayServer,然后让python主动发起调用的。 第一个例子:让python访问了java实现的方法; 第二个例子:让java访问python实现的方法。(通过回调接口) 如果你想让java程序主动”发起调用”,可以直接让java程序开启一个shell进程去打开python脚本。

*****
Written by Lu.dev on 15 July 2019